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
signature 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;
4747struct ResultLocPeerParent;
4848struct ResultLocBitCast;
4949
50enum PtrLen {
51 PtrLenUnknown,
52 PtrLenSingle,
53 PtrLenC,
54};
55
56enum UndefAllowed {
57 UndefOk,
58 UndefBad,
59 LazyOkNoUndef,
60 LazyOk,
61};
62
5063enum X64CABIClass {
5164 X64CABIClass_Unknown,
5265 X64CABIClass_MEMORY,
......@@ -69,9 +82,9 @@ struct IrExecutable {
6982 IrExecutable *source_exec;
7083 IrAnalyze *analysis;
7184 Scope *begin_scope;
85 ErrorMsg *first_err_trace_msg;
7286 ZigList<Tld *> tld_list;
7387
74 bool invalid;
7588 bool is_inline;
7689 bool is_generic_instantiation;
7790 bool need_err_code_spill;
......@@ -255,6 +268,7 @@ enum ConstValSpecial {
255268 ConstValSpecialRuntime,
256269 ConstValSpecialStatic,
257270 ConstValSpecialUndef,
271 ConstValSpecialLazy,
258272};
259273
260274enum RuntimeHintErrorUnion {
......@@ -291,6 +305,82 @@ struct ConstGlobalRefs {
291305 uint32_t align;
292306};
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
294384struct ConstExprValue {
295385 ZigType *type;
296386 ConstValSpecial special;
......@@ -318,6 +408,7 @@ struct ConstExprValue {
318408 ConstPtrValue x_ptr;
319409 ConstArgTuple x_arg_tuple;
320410 Buf *x_enum_literal;
411 LazyValue *x_lazy;
321412
322413 // populated if special == ConstValSpecialRuntime
323414 RuntimeHintErrorUnion rh_error_union;
......@@ -364,6 +455,7 @@ enum TldResolution {
364455 TldResolutionUnresolved,
365456 TldResolutionResolving,
366457 TldResolutionInvalid,
458 TldResolutionOkLazy,
367459 TldResolutionOk,
368460};
369461
......@@ -420,10 +512,12 @@ struct TypeEnumField {
420512
421513struct TypeUnionField {
422514 Buf *name;
515 ZigType *type_entry; // available after ResolveStatusSizeKnown
516 ConstExprValue *type_val; // available after ResolveStatusZeroBitsKnown
423517 TypeEnumField *enum_field;
424 ZigType *type_entry;
425518 AstNode *decl_node;
426519 uint32_t gen_index;
520 uint32_t align;
427521};
428522
429523enum NodeType {
......@@ -849,6 +943,8 @@ struct AstNodeStructField {
849943 Buf *name;
850944 AstNode *type;
851945 AstNode *value;
946 // populated if the "align(A)" is present
947 AstNode *align_expr;
852948};
853949
854950struct AstNodeStringLiteral {
......@@ -944,6 +1040,7 @@ struct AstNodeEnumLiteral {
9441040
9451041struct AstNode {
9461042 enum NodeType type;
1043 bool already_traced_this_node;
9471044 size_t line;
9481045 size_t column;
9491046 ZigType *owner;
......@@ -1039,12 +1136,6 @@ struct FnTypeId {
10391136uint32_t fn_type_id_hash(FnTypeId*);
10401137bool fn_type_id_eql(FnTypeId *a, FnTypeId *b);
10411138
1042enum PtrLen {
1043 PtrLenUnknown,
1044 PtrLenSingle,
1045 PtrLenC,
1046};
1047
10481139struct ZigTypePointer {
10491140 ZigType *child_type;
10501141 ZigType *slice_parent;
......@@ -1055,6 +1146,7 @@ struct ZigTypePointer {
10551146 bool is_const;
10561147 bool is_volatile;
10571148 bool allow_zero;
1149 bool resolve_loop_flag_zero_bits;
10581150};
10591151
10601152struct ZigTypeInt {
......@@ -1073,7 +1165,8 @@ struct ZigTypeArray {
10731165
10741166struct TypeStructField {
10751167 Buf *name;
1076 ZigType *type_entry;
1168 ZigType *type_entry; // available after ResolveStatusSizeKnown
1169 ConstExprValue *type_val; // available after ResolveStatusZeroBitsKnown
10771170 size_t src_index;
10781171 size_t gen_index;
10791172 size_t offset; // byte offset from beginning of struct
......@@ -1129,15 +1222,16 @@ struct ZigTypeStruct {
11291222 ResolveStatus resolve_status;
11301223
11311224 bool is_slice;
1132 bool resolve_loop_flag; // set this flag temporarily to detect infinite loops
1133 bool reported_infinite_err;
11341225 // whether any of the fields require comptime
11351226 // known after ResolveStatusZeroBitsKnown
11361227 bool requires_comptime;
1228 bool resolve_loop_flag_zero_bits;
1229 bool resolve_loop_flag_other;
11371230};
11381231
11391232struct ZigTypeOptional {
11401233 ZigType *child_type;
1234 ResolveStatus resolve_status;
11411235};
11421236
11431237struct ZigTypeErrorUnion {
......@@ -1155,26 +1249,20 @@ struct ZigTypeErrorSet {
11551249
11561250struct ZigTypeEnum {
11571251 AstNode *decl_node;
1158 ContainerLayout layout;
1159 uint32_t src_field_count;
11601252 TypeEnumField *fields;
1161 bool is_invalid; // true if any fields are invalid
11621253 ZigType *tag_int_type;
11631254
11641255 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
11751257 LLVMValueRef name_function;
11761258
11771259 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;
11781266};
11791267
11801268uint32_t type_ptr_hash(const ZigType *ptr);
......@@ -1187,7 +1275,7 @@ struct ZigTypeUnion {
11871275 HashMap<Buf *, TypeUnionField *, buf_hash, buf_eql_buf> fields_by_name;
11881276 ZigType *tag_type; // always an enum or null
11891277 LLVMTypeRef union_llvm_type;
1190 ZigType *most_aligned_union_member;
1278 TypeUnionField *most_aligned_union_member;
11911279 size_t gen_union_index;
11921280 size_t gen_tag_index;
11931281 size_t union_abi_size;
......@@ -1199,11 +1287,11 @@ struct ZigTypeUnion {
11991287 ResolveStatus resolve_status;
12001288
12011289 bool have_explicit_tag_type;
1202 bool resolve_loop_flag; // set this flag temporarily to detect infinite loops
1203 bool reported_infinite_err;
12041290 // whether any of the fields require comptime
12051291 // the value is not valid until zero_bits_known == true
12061292 bool requires_comptime;
1293 bool resolve_loop_flag_zero_bits;
1294 bool resolve_loop_flag_other;
12071295};
12081296
12091297struct FnGenParamInfo {
......@@ -1715,6 +1803,7 @@ struct CodeGen {
17151803 //////////////////////////// Runtime State
17161804 LLVMModuleRef module;
17171805 ZigList<ErrorMsg*> errors;
1806 ErrorMsg *trace_err;
17181807 LLVMBuilderRef builder;
17191808 ZigLLVMDIBuilder *dbuilder;
17201809 ZigLLVMDICompileUnit *compile_unit;
......@@ -1767,7 +1856,6 @@ struct CodeGen {
17671856 ZigList<Tld *> resolve_queue;
17681857 size_t resolve_queue_index;
17691858 ZigList<TimeEvent> timing_events;
1770 ZigList<AstNode *> tld_ref_source_node_stack;
17711859 ZigList<ZigFn *> inline_fns;
17721860 ZigList<ZigFn *> test_fns;
17731861 ZigList<ErrorTableEntry *> errors_by_index;
......@@ -1852,7 +1940,6 @@ struct CodeGen {
18521940 ZigFn *main_fn;
18531941 ZigFn *panic_fn;
18541942 TldFn *panic_tld_fn;
1855 AstNode *root_export_decl;
18561943
18571944 WantPIC want_pic;
18581945 WantStackCheck want_stack_check;
......@@ -1940,7 +2027,7 @@ struct CodeGen {
19402027 Buf *zig_lib_dir;
19412028 Buf *zig_std_dir;
19422029 Buf *dynamic_linker_path;
1943 Buf *version_script_path;
2030 Buf *version_script_path;
19442031
19452032 const char **llvm_argv;
19462033 size_t llvm_argv_len;
......@@ -3657,13 +3744,13 @@ enum ResultLocId {
36573744 ResultLocIdBitCast,
36583745};
36593746
3660// Additions to this struct may need to be handled in
3747// Additions to this struct may need to be handled in
36613748// ir_reset_result
36623749struct ResultLoc {
36633750 ResultLocId id;
36643751 bool written;
36653752 bool allow_write_through_const;
3666 IrInstruction *resolved_loc; // result ptr
3753 IrInstruction *resolved_loc; // result ptr
36673754 IrInstruction *source_instruction;
36683755 IrInstruction *gen_instruction; // value to store to the result loc
36693756 ZigType *implicit_elem_type;
src/analyze.cpp+853-479
......@@ -20,7 +20,7 @@
2020
2121static 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
2525static Error ATTRIBUTE_MUST_USE resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type);
2626static 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) {
5959 root_struct->source_code, root_struct->line_offsets, msg);
6060
6161 g->errors.append(err);
62 g->trace_err = err;
6263 return err;
6364}
6465
65ErrorMsg *add_node_error(CodeGen *g, const AstNode *node, Buf *msg) {
66ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg) {
6667 Token fake_token;
6768 fake_token.start_line = node->line;
6869 fake_token.start_column = node->column;
70 node->already_traced_this_node = true;
6971 return add_token_error(g, node->owner, &fake_token, msg);
7072}
7173
......@@ -271,6 +273,8 @@ bool type_is_resolved(ZigType *type_entry, ResolveStatus status) {
271273 return type_entry->data.structure.resolve_status >= status;
272274 case ZigTypeIdUnion:
273275 return type_entry->data.unionation.resolve_status >= status;
276 case ZigTypeIdEnum:
277 return type_entry->data.enumeration.resolve_status >= status;
274278 case ZigTypeIdFnFrame:
275279 switch (status) {
276280 case ResolveStatusInvalid:
......@@ -285,32 +289,28 @@ bool type_is_resolved(ZigType *type_entry, ResolveStatus status) {
285289 case ResolveStatusLLVMFull:
286290 return type_entry->llvm_type != nullptr;
287291 }
288 case ZigTypeIdEnum:
292 case ZigTypeIdOpaque:
293 return status < ResolveStatusSizeKnown;
294 case ZigTypeIdPointer:
289295 switch (status) {
290 case ResolveStatusUnstarted:
291 return true;
292296 case ResolveStatusInvalid:
293297 zig_unreachable();
298 case ResolveStatusUnstarted:
299 return true;
294300 case ResolveStatusZeroBitsKnown:
295 return type_entry->data.enumeration.zero_bits_known;
296301 case ResolveStatusAlignmentKnown:
297 return type_entry->data.enumeration.zero_bits_known;
298302 case ResolveStatusSizeKnown:
299 return type_entry->data.enumeration.complete;
303 return type_entry->abi_size != SIZE_MAX;
300304 case ResolveStatusLLVMFwdDecl:
301305 case ResolveStatusLLVMFull:
302 return type_entry->llvm_di_type != nullptr;
306 return type_entry->llvm_type != nullptr;
303307 }
304 zig_unreachable();
305 case ZigTypeIdOpaque:
306 return status < ResolveStatusSizeKnown;
307308 case ZigTypeIdMetaType:
308309 case ZigTypeIdVoid:
309310 case ZigTypeIdBool:
310311 case ZigTypeIdUnreachable:
311312 case ZigTypeIdInt:
312313 case ZigTypeIdFloat:
313 case ZigTypeIdPointer:
314314 case ZigTypeIdArray:
315315 case ZigTypeIdComptimeFloat:
316316 case ZigTypeIdComptimeInt:
......@@ -460,8 +460,6 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
460460 }
461461 }
462462
463 assert(type_is_resolved(child_type, ResolveStatusZeroBitsKnown));
464
465463 ZigType *entry = new_type_table_entry(ZigTypeIdPointer);
466464
467465 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
491489 buf_ptr(&child_type->name));
492490 }
493491
494 assert(child_type->id != ZigTypeIdInvalid);
495
496 if (type_has_bits(child_type)) {
497 entry->abi_size = g->builtin_types.entry_usize->abi_size;
498 entry->size_in_bits = g->builtin_types.entry_usize->size_in_bits;
499 entry->abi_align = g->builtin_types.entry_usize->abi_align;
492 if (type_is_resolved(child_type, ResolveStatusZeroBitsKnown)) {
493 if (type_has_bits(child_type)) {
494 entry->abi_size = g->builtin_types.entry_usize->abi_size;
495 entry->size_in_bits = g->builtin_types.entry_usize->size_in_bits;
496 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 }
500503 } else {
501 assert(byte_alignment == 0);
502 entry->abi_size = 0;
503 entry->size_in_bits = 0;
504 entry->abi_align = 0;
504 entry->abi_size = SIZE_MAX;
505 entry->size_in_bits = SIZE_MAX;
506 entry->abi_align = UINT32_MAX;
505507 }
506508
507509 entry->data.pointer.ptr_len = ptr_len;
......@@ -564,6 +566,7 @@ ZigType *get_optional_type(CodeGen *g, ZigType *child_type) {
564566 }
565567
566568 entry->data.maybe.child_type = child_type;
569 entry->data.maybe.resolve_status = ResolveStatusSizeKnown;
567570
568571 child_type->optional_parent = entry;
569572 return entry;
......@@ -865,7 +868,7 @@ ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
865868 return table_entry->value;
866869 }
867870 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)))
869872 return g->builtin_types.entry_invalid;
870873 assert(fn_type_id->return_type->id != ZigTypeIdOpaque);
871874 } else {
......@@ -960,31 +963,276 @@ ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind
960963 return entry;
961964}
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{
964969 size_t backward_branch_count = 0;
965970 size_t backward_branch_quota = default_backward_branch_quota;
966971 return ir_eval_const_value(g, scope, node, type_entry,
967972 &backward_branch_count, &backward_branch_quota,
968 nullptr, nullptr, node, type_name, nullptr, nullptr);
973 nullptr, nullptr, node, type_name, nullptr, nullptr, undef);
969974}
970975
971ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) {
972 ConstExprValue *result = analyze_const_value(g, scope, node, g->builtin_types.entry_type, nullptr);
973 if (type_is_invalid(result->type))
974 return g->builtin_types.entry_invalid;
976static Error type_val_resolve_zero_bits(CodeGen *g, ConstExprValue *type_val, ZigType *parent_type,
977 ConstExprValue *parent_type_val, bool *is_zero_bits)
978{
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);
977 // Reject undefined as valid `type` type even though the specification
978 // allows it to be casted to anything.
979 // See also ir_resolve_type()
980 if (result->special == ConstValSpecialUndef) {
981 add_node_error(g, node,
982 buf_sprintf("expected type 'type', found '%s'",
983 buf_ptr(&g->builtin_types.entry_undef->name)));
984 return g->builtin_types.entry_invalid;
1004 if (parent_type_val == &lazy_ptr_type->elem_type->value) {
1005 // Does a struct which contains a pointer field to itself have bits? Yes.
1006 *is_zero_bits = false;
1007 return ErrorNone;
1008 } else {
1009 if (parent_type_val == nullptr) {
1010 parent_type_val = type_val;
1011 }
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 }
9851185 }
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);
9881236 return result->data.x_type;
9891237}
9901238
......@@ -1032,11 +1280,12 @@ void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_cou
10321280}
10331281
10341282static 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);
10361285 if (type_is_invalid(align_result->type))
10371286 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);
10401289 if (align_bytes == 0) {
10411290 add_node_error(g, node, buf_sprintf("alignment must be >= 1"));
10421291 return false;
......@@ -1054,7 +1303,7 @@ static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf **
10541303 ZigType *ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
10551304 PtrLenUnknown, 0, 0, 0, false);
10561305 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);
10581307 if (type_is_invalid(result_val->type))
10591308 return false;
10601309
......@@ -1068,7 +1317,7 @@ static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf **
10681317 return true;
10691318 }
10701319 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);
10721321 Buf *result = buf_alloc();
10731322 buf_resize(result, len);
10741323 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 **
10781327 add_node_error(g, node, buf_sprintf("use of undefined value"));
10791328 return false;
10801329 }
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);
10821331 assert(big_c <= UINT8_MAX);
10831332 uint8_t c = (uint8_t)big_c;
10841333 buf_ptr(result)[i] = c;
......@@ -1404,7 +1653,6 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
14041653 add_node_error(g, proto_node,
14051654 buf_sprintf("TODO implement inferred return types https://github.com/ziglang/zig/issues/447"));
14061655 return g->builtin_types.entry_invalid;
1407 //return get_generic_fn_type(g, &fn_type_id);
14081656 }
14091657
14101658 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
14231671 }
14241672
14251673 if (!calling_convention_allows_zig_types(fn_type_id.cc) &&
1426 fn_type_id.return_type->id != ZigTypeIdVoid &&
1427 !type_allowed_in_extern(g, fn_type_id.return_type))
1674 fn_type_id.return_type->id != ZigTypeIdVoid)
14281675 {
1429 add_node_error(g, fn_proto->return_type,
1430 buf_sprintf("return type '%s' not allowed in function with calling convention '%s'",
1431 buf_ptr(&fn_type_id.return_type->name),
1432 calling_convention_name(fn_type_id.cc)));
1433 return g->builtin_types.entry_invalid;
1676 if ((err = type_resolve(g, fn_type_id.return_type, ResolveStatusSizeKnown)))
1677 return g->builtin_types.entry_invalid;
1678 if (!type_allowed_in_extern(g, fn_type_id.return_type)) {
1679 add_node_error(g, fn_proto->return_type,
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 }
14341685 }
14351686
14361687 switch (fn_type_id.return_type->id) {
......@@ -1490,7 +1741,7 @@ bool type_is_invalid(ZigType *type_entry) {
14901741 case ZigTypeIdUnion:
14911742 return type_entry->data.unionation.resolve_status == ResolveStatusInvalid;
14921743 case ZigTypeIdEnum:
1493 return type_entry->data.enumeration.is_invalid;
1744 return type_entry->data.enumeration.resolve_status == ResolveStatusInvalid;
14941745 default:
14951746 return false;
14961747 }
......@@ -1584,6 +1835,17 @@ static size_t get_abi_size_bytes(size_t size_in_bits, size_t pointer_size_bytes)
15841835 return align_forward(store_size_bytes, abi_align);
15851836}
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
15871849static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
15881850 assert(struct_type->id == ZigTypeIdStruct);
15891851
......@@ -1599,12 +1861,11 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
15991861
16001862 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) {
16031865 if (struct_type->data.structure.resolve_status != ResolveStatusInvalid) {
16041866 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
1605 ErrorMsg *msg = add_node_error(g, decl_node,
1606 buf_sprintf("struct '%s' contains itself", buf_ptr(&struct_type->name)));
1607 emit_error_notes_for_ref_stack(g, msg);
1867 add_node_error(g, decl_node,
1868 buf_sprintf("struct '%s' depends on itself", buf_ptr(&struct_type->name)));
16081869 }
16091870 return ErrorSemanticAnalyzeFail;
16101871 }
......@@ -1615,20 +1876,10 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
16151876 size_t field_count = struct_type->data.structure.src_field_count;
16161877
16171878 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
16201881 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
16321883 size_t packed_bits_offset = 0;
16331884 size_t next_offset = 0;
16341885 size_t first_packed_bits_offset_misalign = SIZE_MAX;
......@@ -1641,13 +1892,25 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
16411892 TypeStructField *field = &struct_type->data.structure.fields[i];
16421893 if (field->gen_index == SIZE_MAX)
16431894 continue;
1644 ZigType *field_type = field->type_entry;
1645 assert(field_type != nullptr);
16461895
16471896 field->gen_index = gen_field_index;
16481897 field->offset = next_offset;
16491898
16501899 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
16511914 size_t field_size_in_bits = type_size_bits(g, field_type);
16521915 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) {
16831946 }
16841947 packed_bits_offset = next_packed_bits_offset;
16851948 } 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
16861958 gen_field_index += 1;
16871959 size_t next_src_field_index = i + 1;
16881960 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) {
16901962 break;
16911963 }
16921964 }
1693 size_t next_abi_align = (next_src_field_index == field_count) ?
1694 abi_align : struct_type->data.structure.fields[next_src_field_index].type_entry->abi_align;
1695 next_offset = next_field_offset(next_offset, abi_align, field_type->abi_size, next_abi_align);
1965 size_t next_align = (next_src_field_index == field_count) ?
1966 abi_align : struct_type->data.structure.fields[next_src_field_index].align;
1967 next_offset = next_field_offset(next_offset, abi_align, field_abi_size, next_align);
16961968 size_in_bits = next_offset * 8;
16971969 }
16981970 }
......@@ -1708,9 +1980,39 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
17081980 struct_type->size_in_bits = size_in_bits;
17091981 struct_type->data.structure.resolve_status = ResolveStatusSizeKnown;
17101982 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;
17121984 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
17142016 return ErrorNone;
17152017}
17162018
......@@ -1728,22 +2030,21 @@ static Error resolve_union_alignment(CodeGen *g, ZigType *union_type) {
17282030 if (union_type->data.unionation.resolve_status >= ResolveStatusAlignmentKnown)
17292031 return ErrorNone;
17302032
1731 if (union_type->data.unionation.resolve_loop_flag) {
1732 if (!union_type->data.unionation.reported_infinite_err) {
1733 AstNode *decl_node = union_type->data.unionation.decl_node;
1734 union_type->data.unionation.reported_infinite_err = true;
2033 AstNode *decl_node = union_type->data.structure.decl_node;
2034
2035 if (union_type->data.unionation.resolve_loop_flag_other) {
2036 if (union_type->data.unionation.resolve_status != ResolveStatusInvalid) {
17352037 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
1736 ErrorMsg *msg = add_node_error(g, decl_node,
1737 buf_sprintf("union '%s' contains itself", buf_ptr(&union_type->name)));
1738 emit_error_notes_for_ref_stack(g, msg);
2038 add_node_error(g, decl_node,
2039 buf_sprintf("union '%s' depends on itself", buf_ptr(&union_type->name)));
17392040 }
17402041 return ErrorSemanticAnalyzeFail;
17412042 }
17422043
17432044 // 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;
17472048 uint32_t field_count = union_type->data.unionation.src_field_count;
17482049 bool packed = union_type->data.unionation.layout == ContainerLayoutPacked;
17492050
......@@ -1752,34 +2053,44 @@ static Error resolve_union_alignment(CodeGen *g, ZigType *union_type) {
17522053 if (field->gen_index == UINT32_MAX)
17532054 continue;
17542055
1755 size_t this_field_align;
1756 if (packed) {
1757 // TODO: https://github.com/ziglang/zig/issues/1512
1758 this_field_align = 1;
1759 // This is the same hack as resolve_struct_alignment. See the comment there.
1760 } else if (field->type_entry == nullptr) {
1761 this_field_align = g->builtin_types.entry_usize->abi_align;
1762 } else {
2056 AstNode *align_expr = field->decl_node->data.struct_field.align_expr;
2057 if (align_expr != nullptr) {
2058 if (!analyze_const_align(g, &union_type->data.unionation.decls_scope->base, align_expr,
2059 &field->align))
2060 {
2061 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
2062 return err;
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) {
17632069 if ((err = type_resolve(g, field->type_entry, ResolveStatusAlignmentKnown))) {
17642070 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;
17662082 }
1767
17682083 if (union_type->data.unionation.resolve_status == ResolveStatusInvalid)
17692084 return ErrorSemanticAnalyzeFail;
1770
1771 this_field_align = field->type_entry->abi_align;
17722085 }
17732086
1774 if (most_aligned_union_member == nullptr ||
1775 this_field_align > most_aligned_union_member->abi_align)
1776 {
1777 most_aligned_union_member = field->type_entry;
2087 if (most_aligned_union_member == nullptr || field->align > most_aligned_union_member->align) {
2088 most_aligned_union_member = field;
17782089 }
17792090 }
17802091
17812092 // unset temporary flag
1782 union_type->data.unionation.resolve_loop_flag = false;
2093 union_type->data.unionation.resolve_loop_flag_other = false;
17832094 union_type->data.unionation.resolve_status = ResolveStatusAlignmentKnown;
17842095 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) {
17932104 union_type->abi_align = tag_type->abi_align;
17942105 union_type->data.unionation.gen_tag_index = SIZE_MAX;
17952106 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) {
17972108 union_type->abi_align = tag_type->abi_align;
17982109 union_type->data.unionation.gen_tag_index = 0;
17992110 union_type->data.unionation.gen_union_index = 1;
18002111 } else {
1801 union_type->abi_align = most_aligned_union_member->abi_align;
2112 union_type->abi_align = most_aligned_union_member->align;
18022113 union_type->data.unionation.gen_union_index = 0;
18032114 union_type->data.unionation.gen_tag_index = 1;
18042115 }
18052116 } else {
18062117 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;
18082119 union_type->data.unionation.gen_union_index = SIZE_MAX;
18092120 union_type->data.unionation.gen_tag_index = SIZE_MAX;
18102121 }
......@@ -1812,6 +2123,17 @@ static Error resolve_union_alignment(CodeGen *g, ZigType *union_type) {
18122123 return ErrorNone;
18132124}
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
18152137static Error resolve_union_type(CodeGen *g, ZigType *union_type) {
18162138 assert(union_type->id == ZigTypeIdUnion);
18172139
......@@ -1831,30 +2153,32 @@ static Error resolve_union_type(CodeGen *g, ZigType *union_type) {
18312153 assert(decl_node->type == NodeTypeContainerDecl);
18322154
18332155 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
18362158 assert(union_type->data.unionation.fields);
18372159
18382160 size_t union_abi_size = 0;
18392161 size_t union_size_in_bits = 0;
18402162
1841 if (union_type->data.unionation.resolve_loop_flag) {
1842 if (!union_type->data.unionation.reported_infinite_err) {
1843 union_type->data.unionation.reported_infinite_err = true;
2163 if (union_type->data.unionation.resolve_loop_flag_other) {
2164 if (union_type->data.unionation.resolve_status != ResolveStatusInvalid) {
18442165 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
1845 ErrorMsg *msg = add_node_error(g, decl_node,
1846 buf_sprintf("union '%s' depends on its own size", buf_ptr(&union_type->name)));
1847 emit_error_notes_for_ref_stack(g, msg);
2166 add_node_error(g, decl_node,
2167 buf_sprintf("union '%s' depends on itself", buf_ptr(&union_type->name)));
18482168 }
18492169 return ErrorSemanticAnalyzeFail;
18502170 }
18512171
18522172 // set temporary flag
1853 union_type->data.unionation.resolve_loop_flag = true;
2173 union_type->data.unionation.resolve_loop_flag_other = true;
18542174
18552175 for (uint32_t i = 0; i < field_count; i += 1) {
18562176 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
18592183 if ((err = type_resolve(g, field_type, ResolveStatusSizeKnown))) {
18602184 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
......@@ -1874,11 +2198,11 @@ static Error resolve_union_type(CodeGen *g, ZigType *union_type) {
18742198 // The union itself for now has to be treated as being independently aligned.
18752199 // See https://github.com/ziglang/zig/issues/2166.
18762200 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);
18782202 }
18792203
18802204 // unset temporary flag
1881 union_type->data.unionation.resolve_loop_flag = false;
2205 union_type->data.unionation.resolve_loop_flag_other = false;
18822206 union_type->data.unionation.resolve_status = ResolveStatusSizeKnown;
18832207 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) {
18972221 field_sizes[union_type->data.unionation.gen_tag_index] = tag_type->abi_size;
18982222 field_aligns[union_type->data.unionation.gen_tag_index] = tag_type->abi_align;
18992223 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;
19012225 size_t field2_offset = next_field_offset(0, union_type->abi_align, field_sizes[0], field_aligns[1]);
19022226 union_type->abi_size = next_field_offset(field2_offset, union_type->abi_align, field_sizes[1], union_type->abi_align);
19032227 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) {
19252249static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
19262250 assert(enum_type->id == ZigTypeIdEnum);
19272251
1928 if (enum_type->data.enumeration.is_invalid)
2252 if (enum_type->data.enumeration.resolve_status == ResolveStatusInvalid)
19292253 return ErrorSemanticAnalyzeFail;
1930
1931 if (enum_type->data.enumeration.zero_bits_known)
2254 if (enum_type->data.enumeration.resolve_status >= ResolveStatusZeroBitsKnown)
19322255 return ErrorNone;
19332256
1934 if (enum_type->data.enumeration.zero_bits_loop_flag) {
1935 ErrorMsg *msg = add_node_error(g, enum_type->data.enumeration.decl_node,
1936 buf_sprintf("'%s' depends on itself", buf_ptr(&enum_type->name)));
1937 emit_error_notes_for_ref_stack(g, msg);
1938 enum_type->data.enumeration.is_invalid = true;
2257 AstNode *decl_node = enum_type->data.enumeration.decl_node;
2258 assert(decl_node->type == NodeTypeContainerDecl);
2259
2260 if (enum_type->data.enumeration.resolve_loop_flag) {
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 }
19392267 return ErrorSemanticAnalyzeFail;
19402268 }
19412269
1942 enum_type->data.enumeration.zero_bits_loop_flag = true;
1943
1944 AstNode *decl_node = enum_type->data.enumeration.decl_node;
1945 assert(decl_node->type == NodeTypeContainerDecl);
2270 enum_type->data.enumeration.resolve_loop_flag = true;
19462271
19472272 assert(!enum_type->data.enumeration.fields);
19482273 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) {
19512276
19522277 enum_type->data.enumeration.src_field_count = field_count;
19532278 enum_type->data.enumeration.fields = nullptr;
1954 enum_type->data.enumeration.is_invalid = true;
1955 enum_type->data.enumeration.zero_bits_loop_flag = false;
1956 enum_type->data.enumeration.zero_bits_known = true;
2279 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
19572280 return ErrorSemanticAnalyzeFail;
19582281 }
19592282
......@@ -1982,14 +2305,14 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
19822305 if (decl_node->data.container_decl.init_arg_expr != nullptr) {
19832306 ZigType *wanted_tag_int_type = analyze_type_expr(g, scope, decl_node->data.container_decl.init_arg_expr);
19842307 if (type_is_invalid(wanted_tag_int_type)) {
1985 enum_type->data.enumeration.is_invalid = true;
2308 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
19862309 } else if (wanted_tag_int_type->id != ZigTypeIdInt) {
1987 enum_type->data.enumeration.is_invalid = true;
2310 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
19882311 add_node_error(g, decl_node->data.container_decl.init_arg_expr,
19892312 buf_sprintf("expected integer, found '%s'", buf_ptr(&wanted_tag_int_type->name)));
19902313 } else if (enum_type->data.enumeration.layout == ContainerLayoutExtern &&
19912314 !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;
19932316 ErrorMsg *msg = add_node_error(g, decl_node->data.container_decl.init_arg_expr,
19942317 buf_sprintf("'%s' is not a valid tag type for an extern enum",
19952318 buf_ptr(&wanted_tag_int_type->name)));
......@@ -2022,6 +2345,11 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
20222345 buf_sprintf("structs and unions, not enums, support field types"));
20232346 add_error_note(g, msg, decl_node,
20242347 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"));
20252353 }
20262354
20272355 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) {
20292357 ErrorMsg *msg = add_node_error(g, field_node,
20302358 buf_sprintf("duplicate enum field: '%s'", buf_ptr(type_enum_field->name)));
20312359 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;
20332361 continue;
20342362 }
20352363
......@@ -2037,9 +2365,10 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
20372365
20382366 if (tag_value != nullptr) {
20392367 // 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);
20412370 if (type_is_invalid(result->type)) {
2042 enum_type->data.enumeration.is_invalid = true;
2371 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
20432372 continue;
20442373 }
20452374
......@@ -2060,7 +2389,7 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
20602389 if (!bigint_fits_in_bits(&type_enum_field->value,
20612390 tag_int_type->size_in_bits,
20622391 tag_int_type->data.integral.is_signed)) {
2063 enum_type->data.enumeration.is_invalid = true;
2392 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
20642393
20652394 Buf *val_buf = buf_alloc();
20662395 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) {
20752404 // Make sure the value is unique
20762405 auto entry = occupied_tag_values.put_unique(type_enum_field->value, field_node);
20772406 if (entry != nullptr) {
2078 enum_type->data.enumeration.is_invalid = true;
2407 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
20792408
20802409 Buf *val_buf = buf_alloc();
20812410 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) {
20892418 last_enum_field = type_enum_field;
20902419 }
20912420
2092 enum_type->data.enumeration.zero_bits_loop_flag = false;
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)
2421 if (enum_type->data.enumeration.resolve_status == ResolveStatusInvalid)
20972422 return ErrorSemanticAnalyzeFail;
20982423
2424 enum_type->data.enumeration.resolve_loop_flag = false;
2425 enum_type->data.enumeration.resolve_status = ResolveStatusSizeKnown;
2426
20992427 return ErrorNone;
21002428}
21012429
......@@ -2112,16 +2440,17 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
21122440 AstNode *decl_node = struct_type->data.structure.decl_node;
21132441 assert(decl_node->type == NodeTypeContainerDecl);
21142442
2115 if (struct_type->data.structure.resolve_loop_flag) {
2116 // TODO This is a problem. I believe it can be solved with lazy values.
2117 struct_type->size_in_bits = SIZE_MAX;
2118 struct_type->abi_size = SIZE_MAX;
2119 struct_type->data.structure.resolve_status = ResolveStatusZeroBitsKnown;
2120 struct_type->data.structure.resolve_loop_flag = false;
2121 return ErrorNone;
2443 if (struct_type->data.structure.resolve_loop_flag_zero_bits) {
2444 if (struct_type->data.structure.resolve_status != ResolveStatusInvalid) {
2445 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2446 add_node_error(g, decl_node,
2447 buf_sprintf("struct '%s' depends on itself",
2448 buf_ptr(&struct_type->name)));
2449 }
2450 return ErrorSemanticAnalyzeFail;
21222451 }
21232452
2124 struct_type->data.structure.resolve_loop_flag = true;
2453 struct_type->data.structure.resolve_loop_flag_zero_bits = true;
21252454
21262455 assert(!struct_type->data.structure.fields);
21272456 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) {
21532482 return ErrorSemanticAnalyzeFail;
21542483 }
21552484
2156 ZigType *field_type = analyze_type_expr(g, scope, field_node->data.struct_field.type);
2157 type_struct_field->type_entry = field_type;
2158 if (type_is_invalid(field_type)) {
2485 ConstExprValue *field_type_val = analyze_const_value(g, scope,
2486 field_node->data.struct_field.type, g->builtin_types.entry_type, nullptr, LazyOkNoUndef);
2487 if (type_is_invalid(field_type_val->type)) {
21592488 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
21602489 return ErrorSemanticAnalyzeFail;
21612490 }
2491 assert(field_type_val->special != ConstValSpecialRuntime);
2492 type_struct_field->type_val = field_type_val;
21622493 if (struct_type->data.structure.resolve_status == ResolveStatusInvalid)
21632494 return ErrorSemanticAnalyzeFail;
21642495
2165 if (struct_type->data.structure.layout == ContainerLayoutExtern &&
2166 !type_allowed_in_extern(g, field_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)));
2496 bool field_is_opaque_type;
2497 if ((err = type_val_resolve_is_opaque_type(g, field_type_val, &field_is_opaque_type))) {
21712498 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
21722499 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 }
21782500 }
2179
2180 type_struct_field->src_index = i;
2181 type_struct_field->gen_index = SIZE_MAX;
2182
2183 if (field_type->id == ZigTypeIdOpaque) {
2501 if (field_is_opaque_type) {
21842502 add_node_error(g, field_node->data.struct_field.type,
21852503 buf_sprintf("opaque types have unknown size and therefore cannot be directly embedded in structs"));
21862504 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
21872505 return ErrorSemanticAnalyzeFail;
21882506 }
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)) {
21902512 case ReqCompTimeYes:
21912513 struct_type->data.structure.requires_comptime = true;
21922514 break;
21932515 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 }
21942520 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
21952521 return ErrorSemanticAnalyzeFail;
21962522 case ReqCompTimeNo:
21972523 break;
21982524 }
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)
22012532 continue;
22022533
22032534 type_struct_field->gen_index = gen_field_index;
22042535 gen_field_index += 1;
22052536 }
22062537
2207 struct_type->data.structure.resolve_loop_flag = false;
2538 struct_type->data.structure.resolve_loop_flag_zero_bits = false;
22082539 struct_type->data.structure.gen_field_count = (uint32_t)gen_field_index;
22092540 if (gen_field_index != 0) {
22102541 struct_type->abi_size = SIZE_MAX;
......@@ -2234,17 +2565,16 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) {
22342565
22352566 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) {
22382569 if (struct_type->data.structure.resolve_status != ResolveStatusInvalid) {
22392570 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2240 ErrorMsg *msg = add_node_error(g, decl_node,
2241 buf_sprintf("struct '%s' contains itself", buf_ptr(&struct_type->name)));
2242 emit_error_notes_for_ref_stack(g, msg);
2571 add_node_error(g, decl_node,
2572 buf_sprintf("struct '%s' depends on itself", buf_ptr(&struct_type->name)));
22432573 }
22442574 return ErrorSemanticAnalyzeFail;
22452575 }
22462576
2247 struct_type->data.structure.resolve_loop_flag = true;
2577 struct_type->data.structure.resolve_loop_flag_other = true;
22482578 assert(decl_node->type == NodeTypeContainerDecl);
22492579
22502580 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) {
22552585 if (field->gen_index == SIZE_MAX)
22562586 continue;
22572587
2258 size_t this_field_align;
2259 if (packed) {
2260 // TODO: https://github.com/ziglang/zig/issues/1512
2261 this_field_align = 1;
2262 // TODO If we have no type_entry for the field, we've already failed to
2263 // compile the program correctly. This stage1 compiler needs a deeper
2264 // reworking to make this correct, or we can ignore the problem
2265 // and make sure it is fixed in stage2. This workaround is for when
2266 // there is a false positive of a dependency loop, of alignment depending
2267 // on itself. When this false positive happens we assume a pointer-aligned
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;
2588 AstNode *align_expr = field->decl_node->data.struct_field.align_expr;
2589 if (align_expr != nullptr) {
2590 if (!analyze_const_align(g, &struct_type->data.structure.decls_scope->base, align_expr,
2591 &field->align))
2592 {
2593 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2594 return err;
2595 }
2596 } else if (packed) {
2597 field->align = 1;
22722598 } 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 }
22742604 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2275 return ErrorSemanticAnalyzeFail;
2605 return err;
22762606 }
2277 this_field_align = field->type_entry->abi_align;
2607 if (struct_type->data.structure.resolve_status == ResolveStatusInvalid)
2608 return ErrorSemanticAnalyzeFail;
22782609 }
22792610
2280 // TODO: https://github.com/ziglang/zig/issues/1512
2281 if (this_field_align > struct_type->abi_align) {
2282 struct_type->abi_align = this_field_align;
2611 if (field->align > struct_type->abi_align) {
2612 struct_type->abi_align = field->align;
22832613 }
22842614 }
22852615
2286 struct_type->data.structure.resolve_loop_flag = false;
2616 struct_type->data.structure.resolve_loop_flag_other = false;
22872617
22882618 if (struct_type->data.structure.resolve_status == ResolveStatusInvalid) {
22892619 return ErrorSemanticAnalyzeFail;
......@@ -2304,23 +2634,21 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
23042634 if (union_type->data.unionation.resolve_status >= ResolveStatusZeroBitsKnown)
23052635 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
23212637 AstNode *decl_node = union_type->data.unionation.decl_node;
23222638 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
23242652 assert(union_type->data.unionation.fields == nullptr);
23252653 uint32_t field_count = (uint32_t)decl_node->data.container_decl.fields.length;
23262654 if (field_count == 0) {
......@@ -2380,14 +2708,13 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
23802708 tag_type->size_in_bits = tag_int_type->size_in_bits;
23812709
23822710 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;
23842712 tag_type->data.enumeration.decl_node = decl_node;
23852713 tag_type->data.enumeration.layout = ContainerLayoutAuto;
23862714 tag_type->data.enumeration.src_field_count = field_count;
23872715 tag_type->data.enumeration.fields = allocate<TypeEnumField>(field_count);
23882716 tag_type->data.enumeration.fields_by_name.init(field_count);
23892717 tag_type->data.enumeration.decls_scope = union_type->data.unionation.decls_scope;
2390 tag_type->data.enumeration.complete = true;
23912718 } else if (enum_type_node != nullptr) {
23922719 ZigType *enum_type = analyze_type_expr(g, scope, enum_type_node);
23932720 if (type_is_invalid(enum_type)) {
......@@ -2429,49 +2756,68 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
24292756 return ErrorSemanticAnalyzeFail;
24302757 }
24312758
2432 ZigType *field_type;
2759 bool field_is_zero_bits;
24332760 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) {
2435 field_type = g->builtin_types.entry_void;
2761 if (decl_node->data.container_decl.auto_enum ||
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;
24362766 } else {
24372767 add_node_error(g, field_node, buf_sprintf("union field missing type"));
24382768 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
24392769 return ErrorSemanticAnalyzeFail;
24402770 }
24412771 } else {
2442 field_type = analyze_type_expr(g, scope, field_node->data.struct_field.type);
2443 if ((err = type_resolve(g, field_type, ResolveStatusAlignmentKnown))) {
2772 ConstExprValue *field_type_val = analyze_const_value(g, scope,
2773 field_node->data.struct_field.type, g->builtin_types.entry_type, nullptr, LazyOkNoUndef);
2774 if (type_is_invalid(field_type_val->type)) {
24442775 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
24452776 return ErrorSemanticAnalyzeFail;
24462777 }
2778 assert(field_type_val->special != ConstValSpecialRuntime);
2779 union_field->type_val = field_type_val;
24472780 if (union_type->data.unionation.resolve_status == ResolveStatusInvalid)
24482781 return ErrorSemanticAnalyzeFail;
2449 }
2450 union_field->type_entry = field_type;
24512782
2452 if (field_type->id == ZigTypeIdOpaque) {
2453 add_node_error(g, field_node->data.struct_field.type,
2454 buf_sprintf("opaque types have unknown size and therefore cannot be directly embedded in unions"));
2455 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
2456 return ErrorSemanticAnalyzeFail;
2457 }
2783 bool field_is_opaque_type;
2784 if ((err = type_val_resolve_is_opaque_type(g, field_type_val, &field_is_opaque_type))) {
2785 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
2786 return ErrorSemanticAnalyzeFail;
2787 }
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)) {
2460 case ReqCompTimeInvalid:
2796 switch (type_val_resolve_requires_comptime(g, field_type_val)) {
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))) {
24612812 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
24622813 return ErrorSemanticAnalyzeFail;
2463 case ReqCompTimeYes:
2464 union_type->data.unionation.requires_comptime = true;
2465 break;
2466 case ReqCompTimeNo:
2467 break;
2814 }
24682815 }
24692816
24702817 if (field_node->data.struct_field.value != nullptr && !decl_node->data.container_decl.auto_enum) {
24712818 ErrorMsg *msg = add_node_error(g, field_node->data.struct_field.value,
2472 buf_sprintf("non-enum union field assignment"));
2473 add_error_note(g, msg, decl_node,
2474 buf_sprintf("consider 'union(enum)' here"));
2819 buf_create_from_str("untagged union field assignment"));
2820 add_error_note(g, msg, decl_node, buf_create_from_str("consider 'union(enum)' here"));
24752821 }
24762822
24772823 if (create_enum_type) {
......@@ -2489,7 +2835,8 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
24892835 // In a second pass we will fill in the unspecified ones.
24902836 if (tag_value != nullptr) {
24912837 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);
24932840 if (type_is_invalid(result->type)) {
24942841 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
24952842 return ErrorSemanticAnalyzeFail;
......@@ -2530,7 +2877,7 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
25302877 }
25312878 assert(union_field->enum_field != nullptr);
25322879
2533 if (!type_has_bits(field_type))
2880 if (field_is_zero_bits)
25342881 continue;
25352882
25362883 union_field->gen_index = gen_field_index;
......@@ -2607,7 +2954,7 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
26072954 return ErrorSemanticAnalyzeFail;
26082955 }
26092956
2610 union_type->data.unionation.resolve_loop_flag = false;
2957 union_type->data.unionation.resolve_loop_flag_zero_bits = false;
26112958
26122959 union_type->data.unionation.gen_field_count = gen_field_index;
26132960 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) {
26643011 fn_entry->body_node = (proto_node->data.fn_proto.fn_def_node == nullptr) ? nullptr :
26653012 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
26673016 return fn_entry;
26683017}
26693018
......@@ -2690,7 +3039,7 @@ void typecheck_panic_fn(CodeGen *g, TldFn *tld_fn, ZigFn *panic_fn) {
26903039 fake_decl->data.symbol_expr.symbol = tld_fn->base.name;
26913040
26923041 // 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);
26943043}
26953044
26963045ZigType *get_test_fn_type(CodeGen *g) {
......@@ -2836,7 +3185,8 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {
28363185static void resolve_decl_comptime(CodeGen *g, TldCompTime *tld_comptime) {
28373186 assert(tld_comptime->base.source_node->type == NodeTypeCompTime);
28383187 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);
28403190}
28413191
28423192static 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
29313281
29323282void update_compile_var(CodeGen *g, Buf *name, ConstExprValue *value) {
29333283 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);
29353285 assert(tld->id == TldIdVar);
29363286 TldVar *tld_var = (TldVar *)tld;
29373287 tld_var->var->const_value = value;
......@@ -3173,7 +3523,7 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf
31733523 return variable_entry;
31743524}
31753525
3176static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
3526static void resolve_decl_var(CodeGen *g, TldVar *tld_var, bool allow_lazy) {
31773527 AstNode *source_node = tld_var->base.source_node;
31783528 AstNodeVariableDeclaration *var_decl = &source_node->data.variable_declaration;
31793529
......@@ -3185,9 +3535,8 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
31853535 ZigType *explicit_type = nullptr;
31863536 if (var_decl->type) {
31873537 if (tld_var->analyzing_type) {
3188 ErrorMsg *msg = add_node_error(g, var_decl->type,
3538 add_node_error(g, var_decl->type,
31893539 buf_sprintf("type of '%s' depends on itself", buf_ptr(tld_var->base.name)));
3190 emit_error_notes_for_ref_stack(g, msg);
31913540 explicit_type = g->builtin_types.entry_invalid;
31923541 } else {
31933542 tld_var->analyzing_type = true;
......@@ -3205,7 +3554,8 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
32053554 if (explicit_type && explicit_type->id == ZigTypeIdInvalid) {
32063555 implicit_type = explicit_type;
32073556 } 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);
32093559 assert(init_value);
32103560 implicit_type = init_value->type;
32113561
......@@ -3360,7 +3710,8 @@ static void preview_use_decl(CodeGen *g, TldUsingNamespace *using_namespace, Sco
33603710 using_namespace->base.resolution = TldResolutionResolving;
33613711 assert(using_namespace->base.source_node->type == NodeTypeUsingNamespace);
33623712 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);
33643715 using_namespace->using_namespace_value = result;
33653716
33663717 if (type_is_invalid(result->type)) {
......@@ -3380,51 +3731,61 @@ static void preview_use_decl(CodeGen *g, TldUsingNamespace *using_namespace, Sco
33803731 }
33813732}
33823733
3383void resolve_top_level_decl(CodeGen *g, Tld *tld, AstNode *source_node) {
3384 if (tld->resolution != TldResolutionUnresolved)
3734void resolve_top_level_decl(CodeGen *g, Tld *tld, AstNode *source_node, bool allow_lazy) {
3735 bool want_resolve_lazy = tld->resolution == TldResolutionOkLazy && !allow_lazy;
3736 if (tld->resolution != TldResolutionUnresolved && !want_resolve_lazy)
33853737 return;
33863738
3387 assert(tld->resolution != TldResolutionResolving);
33883739 tld->resolution = TldResolutionResolving;
3389 g->tld_ref_source_node_stack.append(source_node);
33903740
33913741 switch (tld->id) {
3392 case TldIdVar:
3393 {
3394 TldVar *tld_var = (TldVar *)tld;
3395 resolve_decl_var(g, tld_var);
3396 break;
3397 }
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;
3742 case TldIdVar: {
3743 TldVar *tld_var = (TldVar *)tld;
3744 if (want_resolve_lazy) {
3745 ir_resolve_lazy(g, source_node, tld_var->var->const_value);
3746 } else {
3747 resolve_decl_var(g, tld_var, allow_lazy);
34153748 }
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 }
34163773 case TldIdUsingNamespace: {
34173774 TldUsingNamespace *tld_using_namespace = (TldUsingNamespace *)tld;
34183775 assert(tld_using_namespace->base.parent_scope->id == ScopeIdDecls);
34193776 ScopeDecls *dest_decls_scope = (ScopeDecls *)tld_using_namespace->base.parent_scope;
34203777 preview_use_decl(g, tld_using_namespace, dest_decls_scope);
34213778 resolve_use_decl(g, tld_using_namespace, dest_decls_scope);
3779
3780 tld->resolution = TldResolutionOk;
34223781 break;
34233782 }
34243783 }
34253784
3426 tld->resolution = TldResolutionOk;
3427 g->tld_ref_source_node_stack.pop();
3785 if (g->trace_err != nullptr && source_node != nullptr && !source_node->already_traced_this_node) {
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 }
34283789}
34293790
34303791Tld *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)
35503911}
35513912
35523913TypeEnumField *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));
35543915 for (uint32_t i = 0; i < enum_type->data.enumeration.src_field_count; i += 1) {
35553916 TypeEnumField *field = &enum_type->data.enumeration.fields[i];
35563917 if (bigint_cmp(&field->value, tag) == CmpEQ) {
......@@ -3619,43 +3980,6 @@ ZigType *container_ref_type(ZigType *type_entry) {
36193980 type_entry->data.pointer.child_type : type_entry;
36203981}
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
36593983ZigType *get_src_ptr_type(ZigType *type) {
36603984 if (type->id == ZigTypeIdPointer) return type;
36613985 if (type->id == ZigTypeIdFn) return type;
......@@ -3791,6 +4115,13 @@ static void resolve_async_fn_frame(CodeGen *g, ZigFn *fn) {
37914115 ZigType *frame_type = get_fn_frame_type(g, fn);
37924116 Error err;
37934117 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 }
37944125 fn->anal_state = FnAnalStateInvalid;
37954126 return;
37964127 }
......@@ -3906,7 +4237,7 @@ static void analyze_fn_ir(CodeGen *g, ZigFn *fn, AstNode *return_type_node) {
39064237 &fn->analyzed_executable, fn_type_id->return_type, return_type_node);
39074238 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) {
39104241 assert(g->errors.length > 0);
39114242 fn->anal_state = FnAnalStateInvalid;
39124243 return;
......@@ -3990,7 +4321,7 @@ static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry) {
39904321 assert(!fn_type->data.fn.is_generic);
39914322
39924323 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) {
39944325 fn_table_entry->anal_state = FnAnalStateInvalid;
39954326 return;
39964327 }
......@@ -4128,12 +4459,14 @@ void semantic_analyze(CodeGen *g) {
41284459 {
41294460 for (; g->resolve_queue_index < g->resolve_queue.length; g->resolve_queue_index += 1) {
41304461 Tld *tld = g->resolve_queue.at(g->resolve_queue_index);
4462 g->trace_err = nullptr;
41314463 AstNode *source_node = nullptr;
4132 resolve_top_level_decl(g, tld, source_node);
4464 resolve_top_level_decl(g, tld, source_node, false);
41334465 }
41344466
41354467 for (; g->fn_defs_index < g->fn_defs.length; g->fn_defs_index += 1) {
41364468 ZigFn *fn_entry = g->fn_defs.at(g->fn_defs_index);
4469 g->trace_err = nullptr;
41374470 analyze_fn_body(g, fn_entry);
41384471 }
41394472 }
......@@ -4145,6 +4478,7 @@ void semantic_analyze(CodeGen *g) {
41454478 // second pass over functions for detecting async
41464479 for (g->fn_defs_index = 0; g->fn_defs_index < g->fn_defs.length; g->fn_defs_index += 1) {
41474480 ZigFn *fn = g->fn_defs.at(g->fn_defs_index);
4481 g->trace_err = nullptr;
41484482 analyze_fn_async(g, fn, true);
41494483 if (fn_is_async(fn) && fn->non_async_node != nullptr) {
41504484 ErrorMsg *msg = add_node_error(g, fn->proto_node,
......@@ -4790,7 +5124,10 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) {
47905124 case ZigTypeIdStruct:
47915125 for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) {
47925126 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) {
47945131 case OnePossibleValueInvalid:
47955132 return OnePossibleValueInvalid;
47965133 case OnePossibleValueNo:
......@@ -4816,18 +5153,19 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) {
48165153 case ZigTypeIdUnion:
48175154 if (type_entry->data.unionation.src_field_count > 1)
48185155 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);
48205161 }
48215162 zig_unreachable();
48225163}
48235164
4824ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) {
5165ReqCompTime type_requires_comptime(CodeGen *g, ZigType *ty) {
48255166 Error err;
4826 if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
4827 return ReqCompTimeInvalid;
4828 switch (type_entry->id) {
5167 switch (ty->id) {
48295168 case ZigTypeIdInvalid:
4830 case ZigTypeIdOpaque:
48315169 zig_unreachable();
48325170 case ZigTypeIdComptimeFloat:
48335171 case ZigTypeIdComptimeInt:
......@@ -4839,23 +5177,36 @@ ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) {
48395177 case ZigTypeIdArgTuple:
48405178 return ReqCompTimeYes;
48415179 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);
48435181 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;
48455189 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;
48475197 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);
48495199 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);
48515201 case ZigTypeIdPointer:
4852 if (type_entry->data.pointer.child_type->id == ZigTypeIdOpaque) {
5202 if (ty->data.pointer.child_type->id == ZigTypeIdOpaque) {
48535203 return ReqCompTimeNo;
48545204 } else {
4855 return type_requires_comptime(g, type_entry->data.pointer.child_type);
5205 return type_requires_comptime(g, ty->data.pointer.child_type);
48565206 }
48575207 case ZigTypeIdFn:
4858 return type_entry->data.fn.is_generic ? ReqCompTimeYes : ReqCompTimeNo;
5208 return ty->data.fn.is_generic ? ReqCompTimeYes : ReqCompTimeNo;
5209 case ZigTypeIdOpaque:
48595210 case ZigTypeIdEnum:
48605211 case ZigTypeIdErrorSet:
48615212 case ZigTypeIdBool:
......@@ -5143,34 +5494,6 @@ ConstExprValue *create_const_arg_tuple(CodeGen *g, size_t arg_index_start, size_
51435494}
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
51745497ConstExprValue *create_const_vals(size_t count) {
51755498 ConstGlobalRefs *global_refs = allocate<ConstGlobalRefs>(count);
51765499 ConstExprValue *vals = allocate<ConstExprValue>(count);
......@@ -5180,10 +5503,6 @@ ConstExprValue *create_const_vals(size_t count) {
51805503 return vals;
51815504}
51825505
5183Error ensure_complete_type(CodeGen *g, ZigType *type_entry) {
5184 return type_resolve(g, type_entry, ResolveStatusSizeKnown);
5185}
5186
51875506static ZigType *get_async_fn_type(CodeGen *g, ZigType *orig_fn_type) {
51885507 if (orig_fn_type->data.fn.fn_type_id.cc == CallingConventionAsync)
51895508 return orig_fn_type;
......@@ -5197,27 +5516,6 @@ static ZigType *get_async_fn_type(CodeGen *g, ZigType *orig_fn_type) {
51975516 return fn_type;
51985517}
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
52215519static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
52225520 Error err;
52235521
......@@ -5229,14 +5527,8 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
52295527
52305528 if (frame_type->data.frame.resolve_loop_type != nullptr) {
52315529 if (!frame_type->data.frame.reported_loop_err) {
5232 frame_type->data.frame.reported_loop_err = true;
5233 ErrorMsg *msg = add_node_error(g, fn->proto_node,
5530 add_node_error(g, fn->proto_node,
52345531 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);
52405532 }
52415533 return ErrorSemanticAnalyzeFail;
52425534 }
......@@ -5252,11 +5544,9 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
52525544 return ErrorSemanticAnalyzeFail;
52535545 break;
52545546 case FnAnalStateProbing: {
5255 ErrorMsg *msg = add_node_error(g, fn->proto_node,
5547 add_node_error(g, fn->proto_node,
52565548 buf_sprintf("cannot resolve '%s': function not fully analyzed yet",
52575549 buf_ptr(&frame_type->name)));
5258 ir_add_analysis_trace(fn->ir_executable.analysis, msg,
5259 buf_sprintf("depends on its own frame here"));
52605550 return ErrorSemanticAnalyzeFail;
52615551 }
52625552 }
......@@ -5327,10 +5617,8 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
53275617 if (callee->anal_state == FnAnalStateProbing) {
53285618 ErrorMsg *msg = add_node_error(g, fn->proto_node,
53295619 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,
53315621 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"));
53345622 return ErrorSemanticAnalyzeFail;
53355623 }
53365624
......@@ -5442,6 +5730,37 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
54425730 return ErrorNone;
54435731}
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
54455764Error type_resolve(CodeGen *g, ZigType *ty, ResolveStatus status) {
54465765 if (type_is_invalid(ty))
54475766 return ErrorSemanticAnalyzeFail;
......@@ -5451,36 +5770,48 @@ Error type_resolve(CodeGen *g, ZigType *ty, ResolveStatus status) {
54515770 case ResolveStatusInvalid:
54525771 zig_unreachable();
54535772 case ResolveStatusZeroBitsKnown:
5454 if (ty->id == ZigTypeIdStruct) {
5455 return resolve_struct_zero_bits(g, ty);
5456 } else if (ty->id == ZigTypeIdEnum) {
5457 return resolve_enum_zero_bits(g, ty);
5458 } else if (ty->id == ZigTypeIdUnion) {
5459 return resolve_union_zero_bits(g, ty);
5773 switch (ty->id) {
5774 case ZigTypeIdStruct:
5775 return resolve_struct_zero_bits(g, ty);
5776 case ZigTypeIdEnum:
5777 return resolve_enum_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;
54605784 }
5461 return ErrorNone;
54625785 case ResolveStatusAlignmentKnown:
5463 if (ty->id == ZigTypeIdStruct) {
5464 return resolve_struct_alignment(g, ty);
5465 } else if (ty->id == ZigTypeIdEnum) {
5466 return resolve_enum_zero_bits(g, ty);
5467 } else if (ty->id == ZigTypeIdUnion) {
5468 return resolve_union_alignment(g, ty);
5469 } else if (ty->id == ZigTypeIdFnFrame) {
5470 return resolve_async_frame(g, ty);
5786 switch (ty->id) {
5787 case ZigTypeIdStruct:
5788 return resolve_struct_alignment(g, ty);
5789 case ZigTypeIdEnum:
5790 return resolve_enum_zero_bits(g, ty);
5791 case ZigTypeIdUnion:
5792 return resolve_union_alignment(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;
54715799 }
5472 return ErrorNone;
54735800 case ResolveStatusSizeKnown:
5474 if (ty->id == ZigTypeIdStruct) {
5475 return resolve_struct_type(g, ty);
5476 } else if (ty->id == ZigTypeIdEnum) {
5477 return resolve_enum_zero_bits(g, ty);
5478 } else if (ty->id == ZigTypeIdUnion) {
5479 return resolve_union_type(g, ty);
5480 } else if (ty->id == ZigTypeIdFnFrame) {
5481 return resolve_async_frame(g, ty);
5801 switch (ty->id) {
5802 case ZigTypeIdStruct:
5803 return resolve_struct_type(g, ty);
5804 case ZigTypeIdEnum:
5805 return resolve_enum_zero_bits(g, ty);
5806 case ZigTypeIdUnion:
5807 return resolve_union_type(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;
54825814 }
5483 return ErrorNone;
54845815 case ResolveStatusLLVMFwdDecl:
54855816 case ResolveStatusLLVMFull:
54865817 resolve_llvm_types(g, ty, status);
......@@ -5855,6 +6186,9 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
58556186 case ConstValSpecialRuntime:
58566187 buf_appendf(buf, "(runtime value)");
58576188 return;
6189 case ConstValSpecialLazy:
6190 buf_appendf(buf, "(lazy value)");
6191 return;
58586192 case ConstValSpecialUndef:
58596193 buf_appendf(buf, "undefined");
58606194 return;
......@@ -5976,7 +6310,7 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
59766310 {
59776311 if (is_slice(type_entry)) {
59786312 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
59816315 ConstExprValue *ptr_val = &const_val->data.x_struct.fields[slice_ptr_index];
59826316 if (ptr_val->special == ConstValSpecialUndef) {
......@@ -6051,12 +6385,12 @@ ZigType *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits) {
60516385 entry->abi_size = LLVMABISizeOfType(g->target_data_ref, entry->llvm_type);
60526386 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) {
60556389 // Override the incorrect alignment reported by LLVM. Clang does this as well.
60566390 // On x86_64 there are some instructions like CMPXCHG16B which require this.
60576391 // On all targets, integers 128 bits and above have ABI alignment of 16.
6392 // However for some targets, LLVM incorrectly reports this as 8.
60586393 // See: https://github.com/ziglang/zig/issues/2987
6059 assert(entry->abi_align == 8); // if this trips we can remove the workaround
60606394 entry->abi_align = 16;
60616395 }
60626396 }
......@@ -6229,6 +6563,40 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) {
62296563 zig_unreachable();
62306564}
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
62326600// Canonicalize the array value as ConstArraySpecialNone
62336601void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {
62346602 size_t elem_count;
......@@ -6492,7 +6860,7 @@ bool type_ptr_eql(const ZigType *a, const ZigType *b) {
64926860
64936861ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name) {
64946862 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);
64966864 assert(tld->id == TldIdVar);
64976865 TldVar *tld_var = (TldVar *)tld;
64986866 ConstExprValue *var_value = tld_var->var->const_value;
......@@ -6707,19 +7075,6 @@ bool ptr_allows_addr_zero(ZigType *ptr_type) {
67077075 return false;
67087076}
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
67237078Buf *type_bare_name(ZigType *type_entry) {
67247079 if (is_slice(type_entry)) {
67257080 return &type_entry->name;
......@@ -7122,10 +7477,9 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS
71227477 struct_type->data.structure.resolve_status = ResolveStatusLLVMFull;
71237478}
71247479
7125static void resolve_llvm_types_enum(CodeGen *g, ZigType *enum_type) {
7126 assert(!enum_type->data.enumeration.is_invalid);
7127 assert(enum_type->data.enumeration.complete);
7128 if (enum_type->llvm_di_type != nullptr) return;
7480static void resolve_llvm_types_enum(CodeGen *g, ZigType *enum_type, ResolveStatus wanted_resolve_status) {
7481 assert(enum_type->data.enumeration.resolve_status >= ResolveStatusSizeKnown);
7482 if (enum_type->data.enumeration.resolve_status >= wanted_resolve_status) return;
71297483
71307484 Scope *scope = &enum_type->data.enumeration.decls_scope->base;
71317485 ZigType *import = get_scope_import(scope);
......@@ -7146,6 +7500,7 @@ static void resolve_llvm_types_enum(CodeGen *g, ZigType *enum_type) {
71467500 debug_align_in_bits,
71477501 ZigLLVM_DIFlags_Zero,
71487502 nullptr, di_element_types, (int)debug_field_count, 0, nullptr, "");
7503 enum_type->data.enumeration.resolve_status = ResolveStatusLLVMFull;
71497504 return;
71507505 }
71517506
......@@ -7178,14 +7533,16 @@ static void resolve_llvm_types_enum(CodeGen *g, ZigType *enum_type) {
71787533 get_llvm_di_type(g, tag_int_type), "");
71797534
71807535 enum_type->llvm_di_type = tag_di_type;
7536 enum_type->data.enumeration.resolve_status = ResolveStatusLLVMFull;
71817537}
71827538
71837539static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveStatus wanted_resolve_status) {
71847540 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;
71877543 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) {
71897546 union_type->llvm_type = get_llvm_type(g, tag_type);
71907547 union_type->llvm_di_type = get_llvm_di_type(g, tag_type);
71917548 union_type->data.unionation.resolve_status = ResolveStatusLLVMFull;
......@@ -7209,7 +7566,6 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta
72097566 if (ResolveStatusLLVMFwdDecl >= wanted_resolve_status) return;
72107567 }
72117568
7212 uint32_t gen_field_count = union_type->data.unionation.gen_field_count;
72137569 ZigLLVMDIType **union_inner_di_types = allocate<ZigLLVMDIType*>(gen_field_count);
72147570 uint32_t field_count = union_type->data.unionation.src_field_count;
72157571 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
72367592 if (tag_type == nullptr || !type_has_bits(tag_type)) {
72377593 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;
72407596 if (padding_bytes > 0) {
72417597 ZigType *u8_type = get_int_type(g, false, 8);
72427598 ZigType *padding_array = get_array_type(g, u8_type, padding_bytes);
72437599 LLVMTypeRef union_element_types[] = {
7244 most_aligned_union_member->llvm_type,
7600 most_aligned_union_member->type_entry->llvm_type,
72457601 get_llvm_type(g, padding_array),
72467602 };
72477603 LLVMStructSetBody(union_type->llvm_type, union_element_types, 2, false);
72487604 } 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);
72507606 }
72517607 union_type->data.unionation.union_llvm_type = union_type->llvm_type;
72527608 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
72577613 ZigLLVMFileToScope(import->data.structure.root_struct->di_file), buf_ptr(&union_type->name),
72587614 import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1),
72597615 union_type->data.unionation.union_abi_size * 8,
7260 most_aligned_union_member->abi_align * 8,
7616 most_aligned_union_member->align * 8,
72617617 ZigLLVM_DIFlags_Zero, union_inner_di_types,
72627618 gen_field_count, 0, "");
72637619
......@@ -7268,14 +7624,14 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta
72687624 }
72697625
72707626 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;
72727628 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);
72747630 } else {
72757631 ZigType *u8_type = get_int_type(g, false, 8);
72767632 ZigType *padding_array = get_array_type(g, u8_type, padding_bytes);
72777633 LLVMTypeRef union_element_types[] = {
7278 get_llvm_type(g, most_aligned_union_member),
7634 get_llvm_type(g, most_aligned_union_member->type_entry),
72797635 get_llvm_type(g, padding_array),
72807636 };
72817637 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
72917647 ZigLLVMDIType *union_di_type = ZigLLVMCreateDebugUnionType(g->dbuilder,
72927648 ZigLLVMTypeToScope(union_type->llvm_di_type), "AnonUnion",
72937649 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,
72957651 ZigLLVM_DIFlags_Zero, union_inner_di_types, gen_field_count, 0, "");
72967652
72977653 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
73027658 ZigLLVMDIType *union_member_di_type = ZigLLVMCreateDebugMemberType(g->dbuilder,
73037659 ZigLLVMTypeToScope(union_type->llvm_di_type), "payload",
73047660 import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1),
7305 most_aligned_union_member->size_in_bits,
7306 8*most_aligned_union_member->abi_align,
7661 most_aligned_union_member->type_entry->size_in_bits,
7662 8*most_aligned_union_member->align,
73077663 union_offset_in_bits,
73087664 ZigLLVM_DIFlags_Zero, union_di_type);
73097665
......@@ -7340,6 +7696,9 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta
73407696static void resolve_llvm_types_pointer(CodeGen *g, ZigType *type, ResolveStatus wanted_resolve_status) {
73417697 if (type->llvm_di_type != nullptr) return;
73427698
7699 if (resolve_pointer_zero_bits(g, type) != ErrorNone)
7700 zig_unreachable();
7701
73437702 if (!type_has_bits(type)) {
73447703 type->llvm_type = g->builtin_types.entry_void->llvm_type;
73457704 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) {
74067765 type->llvm_type = LLVMIntType(type->size_in_bits);
74077766}
74087767
7409static void resolve_llvm_types_optional(CodeGen *g, ZigType *type) {
7410 if (type->llvm_di_type != nullptr) return;
7768static void resolve_llvm_types_optional(CodeGen *g, ZigType *type, ResolveStatus wanted_resolve_status) {
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
74127774 LLVMTypeRef bool_llvm_type = get_llvm_type(g, g->builtin_types.entry_bool);
74137775 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) {
74167778 if (!type_has_bits(child_type)) {
74177779 type->llvm_type = bool_llvm_type;
74187780 type->llvm_di_type = bool_llvm_di_type;
7781 type->data.maybe.resolve_status = ResolveStatusLLVMFull;
74197782 return;
74207783 }
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
74257785 if (type_is_nonnull_ptr(child_type) || child_type->id == ZigTypeIdErrorSet) {
7426 type->llvm_type = child_llvm_type;
7427 type->llvm_di_type = child_llvm_di_type;
7786 type->llvm_type = get_llvm_type(g, child_type);
7787 type->llvm_di_type = get_llvm_di_type(g, child_type);
7788 type->data.maybe.resolve_status = ResolveStatusLLVMFull;
74287789 return;
74297790 }
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
74317811 LLVMTypeRef elem_types[] = {
74327812 get_llvm_type(g, child_type),
74337813 LLVMInt1Type(),
74347814 };
7435 type->llvm_type = LLVMStructType(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);
7815 LLVMStructSetBody(type->llvm_type, elem_types, 2, false);
74437816
74447817 uint64_t val_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, child_llvm_type);
74457818 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) {
74747847
74757848 ZigLLVMReplaceTemporary(g->dbuilder, type->llvm_di_type, replacement_di_type);
74767849 type->llvm_di_type = replacement_di_type;
7850 type->data.maybe.resolve_status = ResolveStatusLLVMFull;
74777851}
74787852
74797853static 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
79098283 else
79108284 return resolve_llvm_types_struct(g, type, wanted_resolve_status, nullptr);
79118285 case ZigTypeIdEnum:
7912 return resolve_llvm_types_enum(g, type);
8286 return resolve_llvm_types_enum(g, type, wanted_resolve_status);
79138287 case ZigTypeIdUnion:
79148288 return resolve_llvm_types_union(g, type, wanted_resolve_status);
79158289 case ZigTypeIdPointer:
......@@ -7917,7 +8291,7 @@ static void resolve_llvm_types(CodeGen *g, ZigType *type, ResolveStatus wanted_r
79178291 case ZigTypeIdInt:
79188292 return resolve_llvm_types_integer(g, type);
79198293 case ZigTypeIdOptional:
7920 return resolve_llvm_types_optional(g, type);
8294 return resolve_llvm_types_optional(g, type, wanted_resolve_status);
79218295 case ZigTypeIdErrorUnion:
79228296 return resolve_llvm_types_error_union(g, type);
79238297 case ZigTypeIdArray:
src/analyze.hpp+9-8
......@@ -11,10 +11,9 @@
1111#include "all_types.hpp"
1212
1313void 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);
1515ErrorMsg *add_token_error(CodeGen *g, ZigType *owner, Token *token, Buf *msg);
1616ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, const AstNode *node, Buf *msg);
17void emit_error_notes_for_ref_stack(CodeGen *g, ErrorMsg *msg);
1817ZigType *new_type_table_entry(ZigTypeId id);
1918ZigType *get_fn_frame_type(CodeGen *g, ZigFn *fn);
2019ZigType *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
5958ZigVar *find_variable(CodeGen *g, Scope *orig_context, Buf *name, ScopeFnDef **crossed_fndef_scope);
6059Tld *find_decl(CodeGen *g, Scope *scope, Buf *name);
6160Tld *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
6463ZigType *get_src_ptr_type(ZigType *type);
6564ZigType *get_codegen_ptr_type(ZigType *type);
......@@ -71,7 +70,6 @@ bool type_is_complete(ZigType *type_entry);
7170bool type_is_resolved(ZigType *type_entry, ResolveStatus status);
7271bool type_is_invalid(ZigType *type_entry);
7372bool type_is_global_error_set(ZigType *err_set_type);
74Error resolve_container_type(CodeGen *g, ZigType *type_entry);
7573ScopeDecls *get_container_scope(ZigType *type_entry);
7674TypeStructField *find_struct_type_field(ZigType *type_entry, Buf *name);
7775TypeEnumField *find_enum_type_field(ZigType *enum_type, Buf *name);
......@@ -95,7 +93,6 @@ ZigFn *create_fn(CodeGen *g, AstNode *proto_node);
9593ZigFn *create_fn_raw(CodeGen *g, FnInline inline_value);
9694void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_count_alloc);
9795AstNode *get_param_decl_node(ZigFn *fn_entry, size_t index);
98Error ATTRIBUTE_MUST_USE ensure_complete_type(CodeGen *g, ZigType *type_entry);
9996Error ATTRIBUTE_MUST_USE type_resolve(CodeGen *g, ZigType *type_entry, ResolveStatus status);
10097void complete_enum(CodeGen *g, ZigType *enum_type);
10198bool ir_get_var_is_comptime(ZigVar *var);
......@@ -169,12 +166,11 @@ ConstExprValue *create_const_slice(CodeGen *g, ConstExprValue *array_val, size_t
169166void init_const_arg_tuple(CodeGen *g, ConstExprValue *const_val, size_t arg_index_start, size_t arg_index_end);
170167ConstExprValue *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
174169ConstExprValue *create_const_vals(size_t count);
175170
176171ZigType *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits);
177172void expand_undef_array(CodeGen *g, ConstExprValue *const_val);
173void expand_undef_struct(CodeGen *g, ConstExprValue *const_val);
178174void update_compile_var(CodeGen *g, Buf *name, ConstExprValue *value);
179175
180176const 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
244240
245241void src_assert(bool ok, AstNode *source_node);
246242bool 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
249246void resolve_llvm_types_fn(CodeGen *g, ZigFn *fn);
250247bool 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
252253#endif
src/bigint.cpp+22-1
......@@ -15,6 +15,8 @@
1515#include <limits>
1616#include <algorithm>
1717
18static uint64_t bigint_as_unsigned(const BigInt *bigint);
19
1820static void bigint_normalize(BigInt *dest) {
1921 const uint64_t *digits = bigint_ptr(dest);
2022
......@@ -1660,7 +1662,7 @@ size_t bigint_clz(const BigInt *bi, size_t bit_count) {
16601662 return count;
16611663}
16621664
1663uint64_t bigint_as_unsigned(const BigInt *bigint) {
1665static uint64_t bigint_as_unsigned(const BigInt *bigint) {
16641666 assert(!bigint->is_negative);
16651667 if (bigint->digit_count == 0) {
16661668 return 0;
......@@ -1671,6 +1673,25 @@ uint64_t bigint_as_unsigned(const BigInt *bigint) {
16711673 }
16721674}
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
16741695int64_t bigint_as_signed(const BigInt *bigint) {
16751696 if (bigint->digit_count == 0) {
16761697 return 0;
src/bigint.hpp+4-1
......@@ -36,7 +36,10 @@ void bigint_init_bigfloat(BigInt *dest, const BigFloat *op);
3636void bigint_init_data(BigInt *dest, const uint64_t *digits, size_t digit_count, bool is_negative);
3737
3838// 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
4043int64_t bigint_as_signed(const BigInt *bigint);
4144
4245static 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
28722872 eval_min_max_value_int(g, int_type, &biggest_possible_err_val, true);
28732873
28742874 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)
28762876 {
28772877 ok_bit = neq_zero_bit;
28782878 } else {
......@@ -3052,8 +3052,10 @@ static LLVMValueRef ir_render_ptr_of_array_to_slice(CodeGen *g, IrExecutable *ex
30523052 IrInstructionPtrOfArrayToSlice *instruction)
30533053{
30543054 ZigType *actual_type = instruction->operand->value.type;
3055 LLVMValueRef expr_val = ir_llvm_value(g, instruction->operand);
3056 assert(expr_val);
3055 ZigType *slice_type = instruction->base.value.type;
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
30583060 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
30613063 ZigType *array_type = actual_type->data.pointer.child_type;
30623064 assert(array_type->id == ZigTypeIdArray);
30633065
3064 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, result_loc, slice_ptr_index, "");
3065 LLVMValueRef indices[] = {
3066 LLVMConstNull(g->builtin_types.entry_usize->llvm_type),
3067 LLVMConstInt(g->builtin_types.entry_usize->llvm_type, 0, false),
3068 };
3069 LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, expr_val, indices, 2, "");
3070 gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false);
3066 if (type_has_bits(actual_type)) {
3067 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, result_loc, ptr_index, "");
3068 LLVMValueRef indices[] = {
3069 LLVMConstNull(g->builtin_types.entry_usize->llvm_type),
3070 LLVMConstInt(g->builtin_types.entry_usize->llvm_type, 0, false),
3071 };
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, "");
30733081 LLVMValueRef len_value = LLVMConstInt(g->builtin_types.entry_usize->llvm_type,
30743082 array_type->data.array.len, false);
30753083 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) {
33863394
33873395static bool value_is_all_undef(ConstExprValue *const_val) {
33883396 switch (const_val->special) {
3397 case ConstValSpecialLazy:
3398 zig_unreachable();
33893399 case ConstValSpecialRuntime:
33903400 return false;
33913401 case ConstValSpecialUndef:
......@@ -3525,6 +3535,8 @@ static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, Ir
35253535}
35263536
35273537static 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);
35283540 ZigVar *var = instruction->var;
35293541 if (type_has_bits(var->var_type)) {
35303542 assert(var->value_ref);
......@@ -6041,6 +6053,7 @@ static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *un
60416053
60426054static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, ConstExprValue *const_val) {
60436055 switch (const_val->special) {
6056 case ConstValSpecialLazy:
60446057 case ConstValSpecialRuntime:
60456058 zig_unreachable();
60466059 case ConstValSpecialUndef:
......@@ -6300,6 +6313,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
63006313 assert(type_has_bits(type_entry));
63016314
63026315 switch (const_val->special) {
6316 case ConstValSpecialLazy:
6317 zig_unreachable();
63036318 case ConstValSpecialRuntime:
63046319 zig_unreachable();
63056320 case ConstValSpecialUndef:
......@@ -6563,7 +6578,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
65636578 uint64_t pad_bytes = type_entry->data.unionation.union_abi_size - field_type_bytes;
65646579 LLVMValueRef correctly_typed_value = gen_const_val(g, payload_value, "");
65656580 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
65686583 {
65696584 if (pad_bytes == 0) {
......@@ -8905,7 +8920,7 @@ static void gen_root_source(CodeGen *g) {
89058920 }
89068921 Tld *panic_tld = find_decl(g, &get_container_scope(import_with_panic)->base, buf_create_from_str("panic"));
89078922 assert(panic_tld != nullptr);
8908 resolve_top_level_decl(g, panic_tld, nullptr);
8923 resolve_top_level_decl(g, panic_tld, nullptr, false);
89098924 }
89108925
89118926
src/ir.cpp+966-580
......@@ -152,11 +152,6 @@ struct ConstCastBadAllowsZero {
152152};
153153
154154
155enum UndefAllowed {
156 UndefOk,
157 UndefBad,
158};
159
160155static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope);
161156static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope, LVal lval,
162157 ResultLoc *result_loc);
......@@ -234,6 +229,7 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c
234229 }
235230 case ConstPtrSpecialBaseStruct: {
236231 ConstExprValue *struct_val = const_val->data.x_ptr.data.base_struct.struct_val;
232 expand_undef_struct(g, struct_val);
237233 result = &struct_val->data.x_struct.fields[const_val->data.x_ptr.data.base_struct.field_index];
238234 break;
239235 }
......@@ -402,7 +398,7 @@ static void ir_ref_var(ZigVar *var) {
402398ZigType *ir_analyze_type_expr(IrAnalyze *ira, Scope *scope, AstNode *node) {
403399 ConstExprValue *result = ir_eval_const_value(ira->codegen, scope, node, ira->codegen->builtin_types.entry_type,
404400 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
407403 if (type_is_invalid(result->type))
408404 return ira->codegen->builtin_types.entry_invalid;
......@@ -5766,7 +5762,7 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode
57665762 buf_sprintf("value %s too large for u32 bit offset", buf_ptr(val_buf)));
57675763 return irb->codegen->invalid_instruction;
57685764 }
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);
57705766 }
57715767
57725768 uint32_t host_int_bytes = 0;
......@@ -5778,7 +5774,7 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode
57785774 buf_sprintf("value %s too large for u32 byte count", buf_ptr(val_buf)));
57795775 return irb->codegen->invalid_instruction;
57805776 }
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);
57825778 }
57835779
57845780 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
68586854 uint32_t len = asm_token.end - asm_token.start - 2;
68596855
68606856 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",
68626858 len, ptr));
68636859 return irb->codegen->invalid_instruction;
68646860 }
......@@ -8111,7 +8107,12 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *sc
81118107 ir_build_reset_result(irb, scope, node, result_loc);
81128108 }
81138109 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 }
81158116 return result;
81168117}
81178118
......@@ -8119,21 +8120,20 @@ static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope) {
81198120 return ir_gen_node_extra(irb, node, scope, LValNone, nullptr);
81208121}
81218122
8122static void invalidate_exec(IrExecutable *exec) {
8123 if (exec->invalid)
8123static void invalidate_exec(IrExecutable *exec, ErrorMsg *msg) {
8124 if (exec->first_err_trace_msg != nullptr)
81248125 return;
81258126
8126 exec->invalid = true;
8127 exec->first_err_trace_msg = msg;
81278128
81288129 for (size_t i = 0; i < exec->tld_list.length; i += 1) {
81298130 exec->tld_list.items[i]->resolution = TldResolutionInvalid;
81308131 }
81318132
81328133 if (exec->source_exec != nullptr)
8133 invalidate_exec(exec->source_exec);
8134 invalidate_exec(exec->source_exec, msg);
81348135}
81358136
8136
81378137bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_executable) {
81388138 assert(node->owner);
81398139
......@@ -8151,8 +8151,10 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
81518151
81528152 IrInstruction *result = ir_gen_node_extra(irb, node, scope, LValNone, nullptr);
81538153 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;
81558156 return false;
8157 }
81568158
81578159 if (!instr_is_unreachable(result)) {
81588160 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
81818183 ir_add_call_stack_errors(codegen, exec->parent_exec, err_msg, limit - 1);
81828184}
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
81908186static ErrorMsg *exec_add_error_node(CodeGen *codegen, IrExecutable *exec, AstNode *source_node, Buf *msg) {
8191 invalidate_exec(exec);
81928187 ErrorMsg *err_msg = add_node_error(codegen, source_node, msg);
8188 invalidate_exec(exec, err_msg);
81938189 if (exec->parent_exec) {
81948190 ir_add_call_stack_errors(codegen, exec, err_msg, 10);
81958191 }
......@@ -8223,6 +8219,7 @@ static Error eval_comptime_ptr_reinterpret(IrAnalyze *ira, CodeGen *codegen, Ast
82238219{
82248220 Error err;
82258221 assert(ptr_val->type->id == ZigTypeIdPointer);
8222 assert(ptr_val->special == ConstValSpecialStatic);
82268223 ConstExprValue tmp = {};
82278224 tmp.special = ConstValSpecialStatic;
82288225 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
90169013 }
90179014
90189015 ConstExprValue *const_val = ir_resolve_const(ira, instruction, UndefBad);
9019 assert(const_val != nullptr);
9016 if (const_val == nullptr)
9017 return false;
90209018
90219019 bool const_val_is_int = (const_val->type->id == ZigTypeIdInt || const_val->type->id == ZigTypeIdComptimeInt);
90229020 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
93769374 result.id = ConstCastResultIdInvalid;
93779375 return result;
93789376 }
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 }
93799385 bool ptr_lens_equal = actual_ptr_type->data.pointer.ptr_len == wanted_ptr_type->data.pointer.ptr_len;
93809386 if ((ptr_lens_equal || wanted_is_c_ptr || actual_is_c_ptr) &&
93819387 type_has_bits(wanted_type) == type_has_bits(actual_type) &&
......@@ -10634,7 +10640,7 @@ static void ir_finish_bb(IrAnalyze *ira) {
1063410640
1063510641static IrInstruction *ir_unreach_error(IrAnalyze *ira) {
1063610642 ira->old_bb_index = SIZE_MAX;
10637 ira->new_irb.exec->invalid = true;
10643 assert(ira->new_irb.exec->first_err_trace_msg != nullptr);
1063810644 return ira->codegen->unreach_instruction;
1063910645}
1064010646
......@@ -10722,32 +10728,57 @@ static IrInstruction *ir_get_const_ptr(IrAnalyze *ira, IrInstruction *instructio
1072210728 return const_instr;
1072310729}
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
1072510765static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed) {
10726 switch (value->value.special) {
10727 case ConstValSpecialStatic:
10728 return &value->value;
10729 case ConstValSpecialRuntime:
10730 if (!type_has_bits(value->value.type)) {
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 }
10766 Error err;
10767 if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec, value->source_node,
10768 &value->value, undef_allowed)))
10769 {
10770 return nullptr;
1074210771 }
10743 zig_unreachable();
10772 return &value->value;
1074410773}
1074510774
1074610775ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
1074710776 ZigType *expected_type, size_t *backward_branch_count, size_t *backward_branch_quota,
1074810777 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)
1075010779{
10780 Error err;
10781
1075110782 if (expected_type != nullptr && type_is_invalid(expected_type))
1075210783 return &codegen->invalid_instruction->value;
1075310784
......@@ -10761,8 +10792,10 @@ ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *nod
1076110792 ir_executable->begin_scope = scope;
1076210793 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;
1076510797 return &codegen->invalid_instruction->value;
10798 }
1076610799
1076710800 if (codegen->verbose_ir) {
1076810801 fprintf(stderr, "\nSource: ");
......@@ -10783,8 +10816,9 @@ ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *nod
1078310816 analyzed_executable->backward_branch_quota = backward_branch_quota;
1078410817 analyzed_executable->begin_scope = scope;
1078510818 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)) {
1078710820 return &codegen->invalid_instruction->value;
10821 }
1078810822
1078910823 if (codegen->verbose_ir) {
1079010824 fprintf(stderr, "{ // (analyzed)\n");
......@@ -10792,7 +10826,14 @@ ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *nod
1079210826 fprintf(stderr, "}\n");
1079310827 }
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;
1079610837}
1079710838
1079810839static ErrorTableEntry *ir_resolve_error(IrAnalyze *ira, IrInstruction *err_value) {
......@@ -10813,22 +10854,43 @@ static ErrorTableEntry *ir_resolve_error(IrAnalyze *ira, IrInstruction *err_valu
1081310854 return const_val->data.x_err_set;
1081410855}
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) {
1081710869 if (type_is_invalid(type_value->value.type))
10818 return ira->codegen->builtin_types.entry_invalid;
10870 return nullptr;
1081910871
1082010872 if (type_value->value.type->id != ZigTypeIdMetaType) {
1082110873 ir_add_error(ira, type_value,
1082210874 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;
1082410876 }
1082510877
10826 ConstExprValue *const_val = ir_resolve_const(ira, type_value, UndefBad);
10827 if (!const_val)
10878 Error err;
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)
1082810891 return ira->codegen->builtin_types.entry_invalid;
1082910892
10830 assert(const_val->data.x_type != nullptr);
10831 return const_val->data.x_type;
10893 return ir_resolve_const_type(ira->codegen, ira->new_irb.exec, type_value->source_node, val);
1083210894}
1083310895
1083410896static 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
1102611088}
1102711089
1102811090static 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)
1103011092{
11031 if (instr_is_comptime(value)) {
11032 zig_panic("TODO comptime frame pointer");
11093 if (instr_is_comptime(frame_ptr)) {
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 }
1103311102 }
1103411103
1103511104 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);
1103711106 result->value.type = wanted_type;
1103811107 return result;
1103911108}
......@@ -11152,6 +11221,9 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi
1115211221 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, value->value.type,
1115311222 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
1115511227 IrInstruction *result_loc;
1115611228 if (type_has_bits(ptr_type) && !handle_is_ptr(value->value.type)) {
1115711229 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
1132211394 IrInstruction *target, ZigType *wanted_type)
1132311395{
1132411396 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
11325 init_const_undefined(ira->codegen, &result->value);
11397 result->value.special = ConstValSpecialUndef;
1132611398 return result;
1132711399}
1132811400
......@@ -11345,10 +11417,13 @@ static IrInstruction *ir_analyze_enum_to_union(IrAnalyze *ira, IrInstruction *so
1134511417 return ira->codegen->invalid_instruction;
1134611418 TypeUnionField *union_field = find_union_field_by_tag(wanted_type, &val->data.x_enum_tag);
1134711419 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)))
1134911424 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)) {
1135211427 case OnePossibleValueInvalid:
1135311428 return ira->codegen->invalid_instruction;
1135411429 case OnePossibleValueNo: {
......@@ -11357,7 +11432,7 @@ static IrInstruction *ir_analyze_enum_to_union(IrAnalyze *ira, IrInstruction *so
1135711432 ErrorMsg *msg = ir_add_error(ira, source_instr,
1135811433 buf_sprintf("cast to union '%s' must initialize '%s' field '%s'",
1135911434 buf_ptr(&wanted_type->name),
11360 buf_ptr(&union_field->type_entry->name),
11435 buf_ptr(&field_type->name),
1136111436 buf_ptr(union_field->name)));
1136211437 add_error_note(ira->codegen, msg, field_node,
1136311438 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
1137311448 bigint_init_bigint(&result->value.data.x_union.tag, &val->data.x_enum_tag);
1137411449 result->value.data.x_union.payload = create_const_vals(1);
1137511450 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;
1137711452 return result;
1137811453 }
1137911454
......@@ -11390,12 +11465,17 @@ static IrInstruction *ir_analyze_enum_to_union(IrAnalyze *ira, IrInstruction *so
1139011465 buf_ptr(&wanted_type->name)));
1139111466 for (uint32_t i = 0; i < wanted_type->data.unionation.src_field_count; i += 1) {
1139211467 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)) {
1139411474 AstNode *field_node = wanted_type->data.unionation.decl_node->data.container_decl.fields.at(i);
1139511475 add_error_note(ira->codegen, msg, field_node,
1139611476 buf_sprintf("field '%s' has type '%s'",
1139711477 buf_ptr(union_field->name),
11398 buf_ptr(&union_field->type_entry->name)));
11478 buf_ptr(&field_type->name)));
1139911479 }
1140011480 }
1140111481 return ira->codegen->invalid_instruction;
......@@ -11461,7 +11541,7 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour
1146111541
1146211542 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)))
1146511545 return ira->codegen->invalid_instruction;
1146611546
1146711547 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
1155011630 return ira->codegen->invalid_instruction;
1155111631 }
1155211632
11553 size_t index = bigint_as_unsigned(&val->data.x_bigint);
11633 size_t index = bigint_as_usize(&val->data.x_bigint);
1155411634 result->value.data.x_err_set = ira->codegen->errors_by_index.at(index);
1155511635 return result;
1155611636 } else {
......@@ -12508,26 +12588,22 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
1250812588 return ir_build_load_ptr_gen(ira, source_instruction, ptr, child_type, result_loc_inst);
1250912589}
1251012590
12511static bool ir_resolve_align(IrAnalyze *ira, IrInstruction *value, uint32_t *out) {
12512 if (type_is_invalid(value->value.type))
12513 return false;
12514
12515 IrInstruction *casted_value = ir_implicit_cast(ira, value, get_align_amt_type(ira->codegen));
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)
12591static bool ir_resolve_const_align(CodeGen *codegen, IrExecutable *exec, AstNode *source_node,
12592 ConstExprValue *const_val, uint32_t *out)
12593{
12594 Error err;
12595 if ((err = ir_resolve_const_val(codegen, exec, source_node, const_val, UndefBad)))
1252112596 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);
1252412599 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"));
1252612601 return false;
1252712602 }
1252812603
1252912604 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));
1253112607 return false;
1253212608 }
1253312609
......@@ -12535,6 +12611,18 @@ static bool ir_resolve_align(IrAnalyze *ira, IrInstruction *value, uint32_t *out
1253512611 return true;
1253612612}
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
1253812626static bool ir_resolve_unsigned(IrAnalyze *ira, IrInstruction *value, ZigType *int_type, uint64_t *out) {
1253912627 if (type_is_invalid(value->value.type))
1254012628 return false;
......@@ -12547,7 +12635,7 @@ static bool ir_resolve_unsigned(IrAnalyze *ira, IrInstruction *value, ZigType *i
1254712635 if (!const_val)
1254812636 return false;
1254912637
12550 *out = bigint_as_unsigned(&const_val->data.x_bigint);
12638 *out = bigint_as_u64(&const_val->data.x_bigint);
1255112639 return true;
1255212640}
1255312641
......@@ -12595,7 +12683,7 @@ static bool ir_resolve_atomic_order(IrAnalyze *ira, IrInstruction *value, Atomic
1259512683 if (!const_val)
1259612684 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);
1259912687 return true;
1260012688}
1260112689
......@@ -12615,7 +12703,7 @@ static bool ir_resolve_atomic_rmw_op(IrAnalyze *ira, IrInstruction *value, Atomi
1261512703 if (!const_val)
1261612704 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);
1261912707 return true;
1262012708}
1262112709
......@@ -12635,7 +12723,7 @@ static bool ir_resolve_global_linkage(IrAnalyze *ira, IrInstruction *value, Glob
1263512723 if (!const_val)
1263612724 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);
1263912727 return true;
1264012728}
1264112729
......@@ -12655,7 +12743,7 @@ static bool ir_resolve_float_mode(IrAnalyze *ira, IrInstruction *value, FloatMod
1265512743 if (!const_val)
1265612744 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);
1265912747 return true;
1266012748}
1266112749
......@@ -12684,7 +12772,7 @@ static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) {
1268412772 return array_val->data.x_array.data.s_buf;
1268512773 }
1268612774 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);
1268812776 Buf *result = buf_alloc();
1268912777 buf_resize(result, len);
1269012778 for (size_t i = 0; i < len; i += 1) {
......@@ -12694,7 +12782,7 @@ static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) {
1269412782 ir_add_error(ira, casted_value, buf_sprintf("use of undefined value"));
1269512783 return nullptr;
1269612784 }
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);
1269812786 assert(big_c <= UINT8_MAX);
1269912787 uint8_t c = (uint8_t)big_c;
1270012788 buf_ptr(result)[i] = c;
......@@ -12719,7 +12807,9 @@ static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructio
1271912807 if (type_is_invalid(operand->value.type))
1272012808 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 {
1272312813 // result location mechanism took care of it.
1272412814 IrInstruction *result = ir_build_return(&ira->new_irb, instruction->base.scope,
1272512815 instruction->base.source_node, nullptr);
......@@ -13576,21 +13666,34 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
1357613666 if (type_is_invalid(casted_op2->value.type))
1357713667 return ira->codegen->invalid_instruction;
1357813668
13579 if (op1->value.special == ConstValSpecialUndef || casted_op2->value.special == ConstValSpecialUndef) {
13580 IrInstruction *result = ir_const(ira, &instruction->base, op1->value.type);
13581 result->value.special = ConstValSpecialUndef;
13582 return result;
13669 // If either operand is undef, result is undef.
13670 ConstExprValue *op1_val = nullptr;
13671 ConstExprValue *op2_val = nullptr;
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);
1358313678 }
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 &&
1358513688 (op1->value.data.x_ptr.special == ConstPtrSpecialHardCodedAddr ||
1358613689 op1->value.data.x_ptr.special == ConstPtrSpecialNull))
1358713690 {
13588 uint64_t start_addr = (op1->value.data.x_ptr.special == ConstPtrSpecialNull) ?
13589 0 : op1->value.data.x_ptr.data.hard_coded_addr.addr;
13691 uint64_t start_addr = (op1_val->data.x_ptr.special == ConstPtrSpecialNull) ?
13692 0 : op1_val->data.x_ptr.data.hard_coded_addr.addr;
1359013693 uint64_t elem_offset;
1359113694 if (!ir_resolve_usize(ira, casted_op2, &elem_offset))
1359213695 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;
1359413697 if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusSizeKnown)))
1359513698 return ira->codegen->invalid_instruction;
1359613699 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
1360213705 } else {
1360313706 zig_unreachable();
1360413707 }
13605 IrInstruction *result = ir_const(ira, &instruction->base, op1->value.type);
13708 IrInstruction *result = ir_const(ira, &instruction->base, op1_val->type);
1360613709 result->value.data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
1360713710 result->value.data.x_ptr.mut = ConstPtrMutRuntimeVar;
1360813711 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
1382913932 op1_array_val = ptr_val->data.x_ptr.data.base_array.array_val;
1383013933 op1_array_index = ptr_val->data.x_ptr.data.base_array.elem_index;
1383113934 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);
1383313936 } else {
1383413937 ir_add_error(ira, op1,
1383513938 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
1386213965 op2_array_val = ptr_val->data.x_ptr.data.base_array.array_val;
1386313966 op2_array_index = ptr_val->data.x_ptr.data.base_array.elem_index;
1386413967 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);
1386613969 } else {
1386713970 ir_add_error(ira, op2,
1386813971 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,
1417114274 }
1417214275 break;
1417314276 case ReqCompTimeNo:
14174 if (init_val != nullptr) {
14175 if (init_val->special == ConstValSpecialStatic &&
14176 init_val->type->id == ZigTypeIdFn &&
14277 if (init_val != nullptr && value_is_comptime(init_val)) {
14278 if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec,
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 &&
1417714284 init_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr &&
1417814285 init_val->data.x_ptr.data.fn.fn_entry->fn_inline == FnInlineAlways)
1417914286 {
......@@ -14231,7 +14338,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,
1423114338 }
1423214339 }
1423314340
14234 if (init_val != nullptr && init_val->special != ConstValSpecialRuntime) {
14341 if (init_val != nullptr && value_is_comptime(init_val)) {
1423514342 // Resolve ConstPtrMutInfer
1423614343 if (var->gen_is_const) {
1423714344 var_ptr->value.data.x_ptr.mut = ConstPtrMutComptimeConst;
......@@ -14242,6 +14349,10 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,
1424214349 // since it's a comptime val there are no instructions for it.
1424314350 // we memcpy the init value here
1424414351 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 }
1424514356 // If this assertion trips, something is wrong with the IR instructions, because
1424614357 // we expected the above deref to return a constant value, but it created a runtime
1424714358 // instruction.
......@@ -14250,7 +14361,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,
1425014361 ir_analyze_store_ptr(ira, var_ptr, var_ptr, deref, false);
1425114362 }
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) {
1425414365 assert(var->mem_slot_index < ira->exec_context.mem_slot_list.length);
1425514366 ConstExprValue *mem_slot = ira->exec_context.mem_slot_list.at(var->mem_slot_index);
1425614367 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,
1451514626static IrInstruction *ir_analyze_instruction_error_union(IrAnalyze *ira,
1451614627 IrInstructionErrorUnion *instruction)
1451714628{
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);
14521 if (type_is_invalid(err_set_type))
14522 return ira->codegen->invalid_instruction;
14523
14524 ZigType *payload_type = ir_resolve_type(ira, instruction->payload->child);
14525 if (type_is_invalid(payload_type))
14526 return ira->codegen->invalid_instruction;
14632 LazyValueErrUnionType *lazy_err_union_type = allocate<LazyValueErrUnionType>(1);
14633 lazy_err_union_type->ira = ira;
14634 result->value.data.x_lazy = &lazy_err_union_type->base;
14635 lazy_err_union_type->base.id = LazyValueIdErrUnionType;
1452714636
14528 if (err_set_type->id != ZigTypeIdErrorSet) {
14529 ir_add_error(ira, instruction->err_set->child,
14530 buf_sprintf("expected error set type, found type '%s'",
14531 buf_ptr(&err_set_type->name)));
14637 lazy_err_union_type->err_set_type = instruction->err_set->child;
14638 if (ir_resolve_type_lazy(ira, lazy_err_union_type->err_set_type) == nullptr)
1453214639 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)
1453614643 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;
1454014646}
1454114647
1454214648static 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
1455514661
1455614662 if ((err = type_resolve(ira->codegen, var_type, ResolveStatusZeroBitsKnown)))
1455714663 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 }
1455814668 assert(result->base.value.data.x_ptr.special != ConstPtrSpecialInvalid);
1455914669
1456014670 pointee->type = var_type;
......@@ -15174,23 +15284,25 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,
1517415284
1517515285 bool comptime_var_mem = ir_get_var_is_comptime(var);
1517615286 bool linkage_makes_it_runtime = var->decl_node->data.variable_declaration.is_extern;
15177 bool is_const = var->src_is_const;
1517815287 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
1518015294 if (linkage_makes_it_runtime)
1518115295 goto no_mem_slot;
1518215296
15183 if (var->const_value->special == ConstValSpecialStatic) {
15297 if (value_is_comptime(var->const_value)) {
1518415298 mem_slot = var->const_value;
15185 } else {
15186 if (var->mem_slot_index != SIZE_MAX && (comptime_var_mem || var->gen_is_const)) {
15187 // find the relevant exec_context
15188 assert(var->owner_exec != nullptr);
15189 assert(var->owner_exec->analysis != nullptr);
15190 IrExecContext *exec_context = &var->owner_exec->analysis->exec_context;
15191 assert(var->mem_slot_index < exec_context->mem_slot_list.length);
15192 mem_slot = exec_context->mem_slot_list.at(var->mem_slot_index);
15193 }
15299 } else if (var->mem_slot_index != SIZE_MAX && (comptime_var_mem || var->gen_is_const)) {
15300 // find the relevant exec_context
15301 assert(var->owner_exec != nullptr);
15302 assert(var->owner_exec->analysis != nullptr);
15303 IrExecContext *exec_context = &var->owner_exec->analysis->exec_context;
15304 assert(var->mem_slot_index < exec_context->mem_slot_list.length);
15305 mem_slot = exec_context->mem_slot_list.at(var->mem_slot_index);
1519415306 }
1519515307
1519615308 if (mem_slot != nullptr) {
......@@ -15198,6 +15310,7 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,
1519815310 case ConstValSpecialRuntime:
1519915311 goto no_mem_slot;
1520015312 case ConstValSpecialStatic: // fallthrough
15313 case ConstValSpecialLazy: // fallthrough
1520115314 case ConstValSpecialUndef: {
1520215315 ConstPtrMut ptr_mut;
1520315316 if (comptime_var_mem) {
......@@ -15208,8 +15321,11 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,
1520815321 assert(!comptime_var_mem);
1520915322 ptr_mut = ConstPtrMutRuntimeVar;
1521015323 }
15211 return ir_get_const_ptr(ira, instruction, mem_slot, var->var_type,
15212 ptr_mut, is_const, is_volatile, var->align_bytes);
15324 result->value.special = ConstValSpecialStatic;
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;
1521315329 }
1521415330 }
1521515331 zig_unreachable();
......@@ -15217,15 +15333,10 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,
1521715333
1521815334no_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
1522515336 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;
1522915340}
1523015341
1523115342// 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
1548915600 AstNode *body_node = fn_entry->body_node;
1549015601 result = ir_eval_const_value(ira->codegen, exec_scope, body_node, return_type,
1549115602 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
1549415606 if (inferred_err_set_type != nullptr) {
1549515607 inferred_err_set_type->data.error_set.infer_fn = nullptr;
......@@ -15513,8 +15625,9 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
1551315625 ira->codegen->memoized_fn_eval_table.put(exec_scope, result);
1551415626 }
1551515627
15516 if (type_is_invalid(result->type))
15628 if (type_is_invalid(result->type)) {
1551715629 return ira->codegen->invalid_instruction;
15630 }
1551815631 }
1551915632
1552015633 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
1568515798 ConstExprValue *align_result = ir_eval_const_value(ira->codegen, impl_fn->child_scope,
1568615799 fn_proto_node->data.fn_proto.align_expr, get_align_amt_type(ira->codegen),
1568715800 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);
1568915803 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
1569015804 impl_fn->child_scope, fn_proto_node->data.fn_proto.align_expr);
1569115805 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
1606616180 zig_unreachable();
1606716181}
1606816182
16069static IrInstruction *ir_analyze_optional_type(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {
16070 Error err;
16071 IrInstruction *value = un_op_instruction->value->child;
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;
16183static IrInstruction *ir_analyze_optional_type(IrAnalyze *ira, IrInstructionUnOp *instruction) {
16184 IrInstruction *result = ir_const(ira, &instruction->base, ira->codegen->builtin_types.entry_type);
16185 result->value.special = ConstValSpecialLazy;
1607716186
16078 switch (type_entry->id) {
16079 case ZigTypeIdInvalid:
16080 zig_unreachable();
16081 case ZigTypeIdMetaType:
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));
16187 LazyValueOptType *lazy_opt_type = allocate<LazyValueOptType>(1);
16188 lazy_opt_type->ira = ira;
16189 result->value.data.x_lazy = &lazy_opt_type->base;
16190 lazy_opt_type->base.id = LazyValueIdOptType;
1610616191
16107 case ZigTypeIdUnreachable:
16108 case ZigTypeIdOpaque:
16109 ir_add_error_node(ira, un_op_instruction->base.source_node,
16110 buf_sprintf("type '%s' not optional", buf_ptr(&type_entry->name)));
16111 return ira->codegen->invalid_instruction;
16112 }
16113 zig_unreachable();
16192 lazy_opt_type->payload_type = instruction->value->child;
16193 if (ir_resolve_type_lazy(ira, lazy_opt_type->payload_type) == nullptr)
16194 return ira->codegen->invalid_instruction;
16195
16196 return result;
1611416197}
1611516198
1611616199static 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
1672716810 return ira->codegen->invalid_instruction;
1672816811
1672916812 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)))
1673116814 return ira->codegen->invalid_instruction;
1673216815
1673316816 uint64_t elem_size = type_size(ira->codegen, return_type->data.pointer.child_type);
1673416817 uint64_t abi_align = get_abi_alignment(ira->codegen, return_type->data.pointer.child_type);
1673516818 uint64_t ptr_align = get_ptr_align(ira->codegen, return_type);
1673616819 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);
1673816821 if (array_type->id == ZigTypeIdArray) {
1673916822 uint64_t array_len = array_type->data.array.len;
1674016823 if (index >= array_len) {
......@@ -16896,7 +16979,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
1689616979 ConstExprValue *len_field = &array_ptr_val->data.x_struct.fields[slice_len_index];
1689716980 IrInstruction *result = ir_const(ira, &elem_ptr_instruction->base, return_type);
1689816981 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);
1690016983 if (index >= slice_len) {
1690116984 ir_add_error_node(ira, elem_ptr_instruction->base.source_node,
1690216985 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,
1700517088 auto entry = container_scope->decl_table.maybe_get(field_name);
1700617089 Tld *tld = entry ? entry->value : nullptr;
1700717090 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);
1700917092 if (tld->resolution == TldResolutionInvalid)
1701017093 return ira->codegen->invalid_instruction;
1701117094 TldFn *tld_fn = (TldFn *)tld;
......@@ -17038,27 +17121,31 @@ static IrInstruction *ir_analyze_container_member_access_inner(IrAnalyze *ira,
1703817121static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction *source_instr,
1703917122 TypeStructField *field, IrInstruction *struct_ptr, ZigType *struct_type, bool initializing)
1704017123{
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)) {
1704217129 case OnePossibleValueInvalid:
1704317130 return ira->codegen->invalid_instruction;
1704417131 case OnePossibleValueYes: {
17045 IrInstruction *elem = ir_const(ira, source_instr, field->type_entry);
17132 IrInstruction *elem = ir_const(ira, source_instr, field_type);
1704617133 return ir_get_ref(ira, source_instr, elem, false, false);
1704717134 }
1704817135 case OnePossibleValueNo:
1704917136 break;
1705017137 }
17138 if ((err = type_resolve(ira->codegen, struct_type, ResolveStatusAlignmentKnown)))
17139 return ira->codegen->invalid_instruction;
1705117140 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);
1705417141 uint32_t ptr_bit_offset = struct_ptr->value.type->data.pointer.bit_offset_in_host;
1705517142 uint32_t ptr_host_int_bytes = struct_ptr->value.type->data.pointer.host_int_bytes;
1705617143 uint32_t host_int_bytes_for_result_type = (ptr_host_int_bytes == 0) ?
1705717144 get_host_int_bytes(ira->codegen, struct_type, field) : ptr_host_int_bytes;
1705817145 bool is_const = struct_ptr->value.type->data.pointer.is_const;
1705917146 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,
17061 is_const, is_volatile, PtrLenSingle, align_bytes,
17147 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field_type,
17148 is_const, is_volatile, PtrLenSingle, field->align,
1706217149 (uint32_t)(ptr_bit_offset + field->bit_offset_in_host),
1706317150 (uint32_t)host_int_bytes_for_result_type, false);
1706417151 if (instr_is_comptime(struct_ptr)) {
......@@ -17113,7 +17200,7 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
1711317200 Error err;
1711417201
1711517202 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)))
1711717204 return ira->codegen->invalid_instruction;
1711817205
1711917206 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,
1724317330}
1724417331
1724517332static IrInstruction *ir_error_dependency_loop(IrAnalyze *ira, IrInstruction *source_instr) {
17246 ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("dependency loop detected"));
17247 emit_error_notes_for_ref_stack(ira->codegen, msg);
17333 ir_add_error(ira, source_instr, buf_sprintf("dependency loop detected"));
1724817334 return ira->codegen->invalid_instruction;
1724917335}
1725017336
1725117337static IrInstruction *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source_instruction, Tld *tld) {
17252 resolve_top_level_decl(ira->codegen, tld, source_instruction->source_node);
17253 if (tld->resolution == TldResolutionInvalid)
17338 resolve_top_level_decl(ira->codegen, tld, source_instruction->source_node, true);
17339 if (tld->resolution == TldResolutionInvalid) {
1725417340 return ira->codegen->invalid_instruction;
17341 }
1725517342
1725617343 switch (tld->id) {
1725717344 case TldIdContainer:
1725817345 case TldIdCompTime:
1725917346 case TldIdUsingNamespace:
1726017347 zig_unreachable();
17261 case TldIdVar:
17262 {
17348 case TldIdVar: {
1726317349 TldVar *tld_var = (TldVar *)tld;
1726417350 ZigVar *var = tld_var->var;
1726517351 if (var == nullptr) {
......@@ -17271,8 +17357,7 @@ static IrInstruction *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source_
1727117357
1727217358 return ir_get_var_ptr(ira, source_instruction, var);
1727317359 }
17274 case TldIdFn:
17275 {
17360 case TldIdFn: {
1727617361 TldFn *tld_fn = (TldFn *)tld;
1727717362 ZigFn *fn_entry = tld_fn->fn_entry;
1727817363 assert(fn_entry->type_entry);
......@@ -17396,7 +17481,7 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc
1739617481 return ira->codegen->invalid_instruction;
1739717482 } else if (is_container(child_type)) {
1739817483 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)))
1740017485 return ira->codegen->invalid_instruction;
1740117486
1740217487 TypeEnumField *field = find_enum_type_field(child_type, field_name);
......@@ -17425,7 +17510,7 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc
1742517510 (child_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr ||
1742617511 child_type->data.unionation.decl_node->data.container_decl.auto_enum))
1742717512 {
17428 if ((err = ensure_complete_type(ira->codegen, child_type)))
17513 if ((err = type_resolve(ira->codegen, child_type, ResolveStatusSizeKnown)))
1742917514 return ira->codegen->invalid_instruction;
1743017515 TypeUnionField *field = find_union_type_field(child_type, field_name);
1743117516 if (field) {
......@@ -17844,65 +17929,29 @@ static IrInstruction *ir_analyze_instruction_any_frame_type(IrAnalyze *ira,
1784417929static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira,
1784517930 IrInstructionSliceType *slice_type_instruction)
1784617931{
17847 Error err;
17848 uint32_t align_bytes = 0;
17932 IrInstruction *result = ir_const(ira, &slice_type_instruction->base, ira->codegen->builtin_types.entry_type);
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
1784917940 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)
1785117943 return ira->codegen->invalid_instruction;
1785217944 }
1785317945
17854 ZigType *child_type = ir_resolve_type(ira, slice_type_instruction->child_type->child);
17855 if (type_is_invalid(child_type))
17946 lazy_slice_type->elem_type = slice_type_instruction->child_type->child;
17947 if (ir_resolve_type_lazy(ira, lazy_slice_type->elem_type) == nullptr)
1785617948 return ira->codegen->invalid_instruction;
1785717949
17858 bool is_const = slice_type_instruction->is_const;
17859 bool is_volatile = slice_type_instruction->is_volatile;
17860 bool is_allow_zero = slice_type_instruction->is_allow_zero;
17950 lazy_slice_type->is_const = slice_type_instruction->is_const;
17951 lazy_slice_type->is_volatile = slice_type_instruction->is_volatile;
17952 lazy_slice_type->is_allowzero = slice_type_instruction->is_allow_zero;
1786117953
17862 switch (child_type->id) {
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();
17954 return result;
1790617955}
1790717956
1790817957static IrInstruction *ir_analyze_instruction_global_asm(IrAnalyze *ira, IrInstructionGlobalAsm *instruction) {
......@@ -18008,7 +18057,7 @@ static IrInstruction *ir_analyze_instruction_array_type(IrAnalyze *ira,
1800818057 case ZigTypeIdFnFrame:
1800918058 case ZigTypeIdAnyFrame:
1801018059 {
18011 if ((err = ensure_complete_type(ira->codegen, child_type)))
18060 if ((err = type_resolve(ira->codegen, child_type, ResolveStatusSizeKnown)))
1801218061 return ira->codegen->invalid_instruction;
1801318062 ZigType *result_type = get_array_type(ira->codegen, child_type, size);
1801418063 return ir_const_type(ira, &array_type_instruction->base, result_type);
......@@ -18024,7 +18073,7 @@ static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira,
1802418073 IrInstruction *type_value = size_of_instruction->type_value->child;
1802518074 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)))
1802818077 return ira->codegen->invalid_instruction;
1802918078
1803018079 switch (type_entry->id) {
......@@ -18529,7 +18578,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
1852918578 if (pointee_val->special == ConstValSpecialRuntime)
1853018579 pointee_val = nullptr;
1853118580 }
18532 if ((err = ensure_complete_type(ira->codegen, target_type)))
18581 if ((err = type_resolve(ira->codegen, target_type, ResolveStatusSizeKnown)))
1853318582 return ira->codegen->invalid_instruction;
1853418583
1853518584 switch (target_type->id) {
......@@ -19070,7 +19119,7 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
1907019119 Scope *analyze_scope = &get_container_scope(container_type)->base;
1907119120 // memoize it
1907219121 field->init_val = analyze_const_value(ira->codegen, analyze_scope, init_node,
19073 field->type_entry, nullptr);
19122 field->type_entry, nullptr, UndefOk);
1907419123 }
1907519124 if (type_is_invalid(field->init_val->type))
1907619125 return ira->codegen->invalid_instruction;
......@@ -19276,8 +19325,7 @@ static IrInstruction *ir_analyze_instruction_compile_err(IrAnalyze *ira,
1927619325 if (!msg_buf)
1927719326 return ira->codegen->invalid_instruction;
1927819327
19279 ErrorMsg *msg = ir_add_error(ira, &instruction->base, msg_buf);
19280 emit_error_notes_for_ref_stack(ira->codegen, msg);
19328 ir_add_error(ira, &instruction->base, msg_buf);
1928119329
1928219330 return ira->codegen->invalid_instruction;
1928319331}
......@@ -19319,7 +19367,10 @@ static IrInstruction *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstruct
1931919367 ZigType *u8_ptr_type = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,
1932019368 true, false, PtrLenUnknown, 0, 0, 0, false);
1932119369 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;
1932319374 ErrorTableEntry *err = casted_value->value.data.x_err_set;
1932419375 if (!err->cached_error_name_val) {
1932519376 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,
1939119442 return ira->codegen->invalid_instruction;
1939219443 }
1939319444
19394 if ((err = ensure_complete_type(ira->codegen, container_type)))
19445 if ((err = type_resolve(ira->codegen, container_type, ResolveStatusSizeKnown)))
1939519446 return ira->codegen->invalid_instruction;
1939619447
1939719448 TypeStructField *field = find_struct_type_field(container_type, field_name);
......@@ -19470,7 +19521,7 @@ static TypeStructField *validate_byte_offset(IrAnalyze *ira,
1947019521 return nullptr;
1947119522
1947219523 Error err;
19473 if ((err = ensure_complete_type(ira->codegen, container_type)))
19524 if ((err = type_resolve(ira->codegen, container_type, ResolveStatusSizeKnown)))
1947419525 return nullptr;
1947519526
1947619527 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
1957419625
1957519626 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
1958019628 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);
1958219631}
1958319632
1958419633static 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
1959419643 ensure_field_index(type_info_declaration_type, "data", 2);
1959519644
1959619645 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)))
1959819647 return err;
1959919648
1960019649 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)))
1960219651 return err;
1960319652
1960419653 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)))
1960619655 return err;
1960719656
1960819657 // 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
1961319662 while ((curr_entry = decl_it.next()) != nullptr) {
1961419663 // If the declaration is unresolved, force it to be resolved again.
1961519664 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);
1961719666 if (curr_entry->value->resolution != TldResolutionOk) {
1961819667 return ErrorSemanticAnalyzeFail;
1961919668 }
......@@ -19673,7 +19722,7 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr
1967319722 case TldIdVar:
1967419723 {
1967519724 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)))
1967719726 return ErrorSemanticAnalyzeFail;
1967819727
1967919728 if (var->const_value->type->id == ZigTypeIdMetaType) {
......@@ -19799,7 +19848,7 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr
1979919848 case TldIdContainer:
1980019849 {
1980119850 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)))
1980319852 return ErrorSemanticAnalyzeFail;
1980419853
1980519854 // This is a type.
......@@ -19855,7 +19904,7 @@ static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_ty
1985519904 return nullptr;
1985619905
1985719906 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
1986019909 ConstExprValue *result = create_const_vals(1);
1986119910 result->special = ConstValSpecialStatic;
......@@ -19867,7 +19916,7 @@ static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_ty
1986719916 // size: Size
1986819917 ensure_field_index(result->type, "size", 0);
1986919918 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));
1987119920 fields[0].special = ConstValSpecialStatic;
1987219921 fields[0].type = type_info_pointer_size_type;
1987319922 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
2034520394 inner_fields[1].special = ConstValSpecialStatic;
2034620395 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;
2034820402 if (!type_has_bits(struct_field->type_entry)) {
2034920403 inner_fields[1].data.x_optional = nullptr;
2035020404 } else {
......@@ -20581,7 +20635,7 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct
2058120635 ZigType *void_type = ira->codegen->builtin_types.entry_void;
2058220636 ConstExprValue *cimport_result = ir_eval_const_value(ira->codegen, &cimport_scope->base, block_node, void_type,
2058320637 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);
2058520639 if (type_is_invalid(cimport_result->type))
2058620640 return ira->codegen->invalid_instruction;
2058720641
......@@ -21181,7 +21235,7 @@ static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstru
2118121235
2118221236 ConstExprValue *len_val = &val->data.x_struct.fields[slice_len_index];
2118321237 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);
2118521239 have_known_len = true;
2118621240 }
2118721241 }
......@@ -21482,64 +21536,75 @@ static IrInstruction *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructio
2148221536 return ira->codegen->invalid_instruction;
2148321537
2148421538 // TODO test this at comptime with u8 and non-u8 types
21485 if (casted_dest_ptr->value.special == ConstValSpecialStatic &&
21486 casted_byte->value.special == ConstValSpecialStatic &&
21487 casted_count->value.special == ConstValSpecialStatic &&
21488 casted_dest_ptr->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr &&
21489 casted_dest_ptr->value.data.x_ptr.mut != ConstPtrMutRuntimeVar)
21539 if (instr_is_comptime(casted_dest_ptr) &&
21540 instr_is_comptime(casted_byte) &&
21541 instr_is_comptime(casted_count))
2149021542 {
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;
21494 size_t start;
21495 size_t bound_end;
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 }
21547 ConstExprValue *byte_val = ir_resolve_const(ira, casted_byte, UndefOk);
21548 if (byte_val == nullptr)
21549 return ira->codegen->invalid_instruction;
2152921550
21530 size_t count = bigint_as_unsigned(&casted_count->value.data.x_bigint);
21531 size_t end = start + count;
21532 if (end > bound_end) {
21533 ir_add_error(ira, count_value, buf_sprintf("out of bounds pointer access"));
21551 ConstExprValue *count_val = ir_resolve_const(ira, casted_count, UndefBad);
21552 if (count_val == nullptr)
2153421553 return ira->codegen->invalid_instruction;
21535 }
2153621554
21537 ConstExprValue *byte_val = &casted_byte->value;
21538 for (size_t i = start; i < end; i += 1) {
21539 copy_const_val(&dest_elements[i], byte_val, true);
21540 }
21555 if (casted_dest_ptr->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr &&
21556 casted_dest_ptr->value.data.x_ptr.mut != ConstPtrMutRuntimeVar)
21557 {
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 }
2154321608 }
2154421609
2154521610 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
2160721672
2160821673 // TODO test this at comptime with u8 and non-u8 types
2160921674 // TODO test with dest ptr being a global runtime variable
21610 if (casted_dest_ptr->value.special == ConstValSpecialStatic &&
21611 casted_src_ptr->value.special == ConstValSpecialStatic &&
21612 casted_count->value.special == ConstValSpecialStatic &&
21613 casted_dest_ptr->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr)
21675 if (instr_is_comptime(casted_dest_ptr) &&
21676 instr_is_comptime(casted_src_ptr) &&
21677 instr_is_comptime(casted_count))
2161421678 {
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;
21618 ConstExprValue *dest_elements;
21619 size_t dest_start;
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 }
21683 ConstExprValue *src_ptr_val = ir_resolve_const(ira, casted_src_ptr, UndefBad);
21684 if (src_ptr_val == nullptr)
21685 return ira->codegen->invalid_instruction;
2165421686
21655 if (dest_start + count > dest_end) {
21656 ir_add_error(ira, &instruction->base, buf_sprintf("out of bounds pointer access"));
21687 ConstExprValue *count_val = ir_resolve_const(ira, casted_count, UndefBad);
21688 if (count_val == nullptr)
2165721689 return ira->codegen->invalid_instruction;
21658 }
2165921690
21660 ConstExprValue *src_ptr_val = &casted_src_ptr->value;
21661 ConstExprValue *src_elements;
21662 size_t src_start;
21663 size_t src_end;
21691 if (dest_ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
21692 size_t count = bigint_as_usize(&count_val->data.x_bigint);
2166421693
21665 switch (src_ptr_val->data.x_ptr.special) {
21666 case ConstPtrSpecialInvalid:
21667 case ConstPtrSpecialDiscard:
21668 zig_unreachable();
21669 case ConstPtrSpecialRef:
21670 src_elements = src_ptr_val->data.x_ptr.data.ref.pointee;
21671 src_start = 0;
21672 src_end = 1;
21673 break;
21674 case ConstPtrSpecialBaseArray:
21675 {
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;
21694 ConstExprValue *dest_elements;
21695 size_t dest_start;
21696 size_t dest_end;
21697 switch (dest_ptr_val->data.x_ptr.special) {
21698 case ConstPtrSpecialInvalid:
21699 case ConstPtrSpecialDiscard:
21700 zig_unreachable();
21701 case ConstPtrSpecialRef:
21702 dest_elements = dest_ptr_val->data.x_ptr.data.ref.pointee;
21703 dest_start = 0;
21704 dest_end = 1;
2168121705 break;
21682 }
21683 case ConstPtrSpecialBaseStruct:
21684 zig_panic("TODO memcpy on const inner struct");
21685 case ConstPtrSpecialBaseErrorUnionCode:
21686 zig_panic("TODO memcpy on const inner error union code");
21687 case ConstPtrSpecialBaseErrorUnionPayload:
21688 zig_panic("TODO memcpy on const inner error union payload");
21689 case ConstPtrSpecialBaseOptionalPayload:
21690 zig_panic("TODO memcpy on const inner optional payload");
21691 case ConstPtrSpecialHardCodedAddr:
21692 zig_unreachable();
21693 case ConstPtrSpecialFunction:
21694 zig_panic("TODO memcpy on ptr cast from function");
21695 case ConstPtrSpecialNull:
21696 zig_panic("TODO memcpy on null ptr");
21697 }
21706 case ConstPtrSpecialBaseArray:
21707 {
21708 ConstExprValue *array_val = dest_ptr_val->data.x_ptr.data.base_array.array_val;
21709 expand_undef_array(ira->codegen, array_val);
21710 dest_elements = array_val->data.x_array.data.s_none.elements;
21711 dest_start = dest_ptr_val->data.x_ptr.data.base_array.elem_index;
21712 dest_end = array_val->type->data.array.len;
21713 break;
21714 }
21715 case ConstPtrSpecialBaseStruct:
21716 zig_panic("TODO memcpy on const inner struct");
21717 case ConstPtrSpecialBaseErrorUnionCode:
21718 zig_panic("TODO memcpy on const inner error union code");
21719 case ConstPtrSpecialBaseErrorUnionPayload:
21720 zig_panic("TODO memcpy on const inner error union payload");
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) {
21700 ir_add_error(ira, &instruction->base, buf_sprintf("out of bounds pointer access"));
21701 return ira->codegen->invalid_instruction;
21702 }
21731 if (dest_start + count > dest_end) {
21732 ir_add_error(ira, &instruction->base, buf_sprintf("out of bounds pointer access"));
21733 return ira->codegen->invalid_instruction;
21734 }
2170321735
21704 // TODO check for noalias violations - this should be generalized to work for any function
21736 ConstExprValue *src_elements;
21737 size_t src_start;
21738 size_t src_end;
2170521739
21706 for (size_t i = 0; i < count; i += 1) {
21707 copy_const_val(&dest_elements[dest_start + i], &src_elements[src_start + i], true);
21708 }
21740 switch (src_ptr_val->data.x_ptr.special) {
21741 case ConstPtrSpecialInvalid:
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 }
2171121787 }
2171221788
2171321789 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
2187721953 if (slice_ptr == nullptr)
2187821954 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
2188021961 parent_ptr = &slice_ptr->data.x_struct.fields[slice_ptr_index];
2188121962 if (parent_ptr->special == ConstValSpecialUndef) {
2188221963 ir_add_error(ira, &instruction->base, buf_sprintf("slice of undefined"));
......@@ -21897,7 +21978,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
2189721978 case ConstPtrSpecialBaseArray:
2189821979 array_val = parent_ptr->data.x_ptr.data.base_array.array_val;
2189921980 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);
2190121982 break;
2190221983 case ConstPtrSpecialBaseStruct:
2190321984 zig_panic("TODO slice const inner struct");
......@@ -21910,7 +21991,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
2191021991 case ConstPtrSpecialHardCodedAddr:
2191121992 array_val = nullptr;
2191221993 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);
2191421995 break;
2191521996 case ConstPtrSpecialFunction:
2191621997 zig_panic("TODO slice of slice cast from function");
......@@ -21921,7 +22002,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
2192122002 zig_unreachable();
2192222003 }
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);
2192522006 if (!ptr_is_undef && start_scalar > rel_end) {
2192622007 ir_add_error(ira, &instruction->base, buf_sprintf("out of bounds slice"));
2192722008 return ira->codegen->invalid_instruction;
......@@ -21929,7 +22010,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
2192922010
2193022011 uint64_t end_scalar;
2193122012 if (end) {
21932 end_scalar = bigint_as_unsigned(&end->value.data.x_bigint);
22013 end_scalar = bigint_as_u64(&end->value.data.x_bigint);
2193322014 } else {
2193422015 end_scalar = rel_end;
2193522016 }
......@@ -22021,7 +22102,7 @@ static IrInstruction *ir_analyze_instruction_member_count(IrAnalyze *ira, IrInst
2202122102 return ira->codegen->invalid_instruction;
2202222103 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)))
2202522106 return ira->codegen->invalid_instruction;
2202622107
2202722108 uint64_t result;
......@@ -22057,7 +22138,7 @@ static IrInstruction *ir_analyze_instruction_member_type(IrAnalyze *ira, IrInstr
2205722138 if (type_is_invalid(container_type))
2205822139 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)))
2206122142 return ira->codegen->invalid_instruction;
2206222143
2206322144
......@@ -22100,7 +22181,7 @@ static IrInstruction *ir_analyze_instruction_member_name(IrAnalyze *ira, IrInstr
2210022181 if (type_is_invalid(container_type))
2210122182 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)))
2210422185 return ira->codegen->invalid_instruction;
2210522186
2210622187 uint64_t member_index;
......@@ -22249,53 +22330,24 @@ static IrInstruction *ir_analyze_instruction_frame_size(IrAnalyze *ira, IrInstru
2224922330}
2225022331
2225122332static IrInstruction *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstructionAlignOf *instruction) {
22252 Error err;
22253 IrInstruction *type_value = instruction->type_value->child;
22254 if (type_is_invalid(type_value->value.type))
22255 return ira->codegen->invalid_instruction;
22256 ZigType *type_entry = ir_resolve_type(ira, type_value);
22333 // Here we create a lazy value in order to avoid resolving the alignment of the type
22334 // immediately. This avoids false positive dependency loops such as:
22335 // const Node = struct {
22336 // field: []align(@alignOf(Node)) Node,
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)
2225922348 return ira->codegen->invalid_instruction;
2226022349
22261 switch (type_entry->id) {
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();
22350 return result;
2229922351}
2230022352
2230122353static IrInstruction *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInstructionOverflowOp *instruction) {
......@@ -22359,13 +22411,26 @@ static IrInstruction *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInstr
2235922411 if (type_is_invalid(casted_result_ptr->value.type))
2236022412 return ira->codegen->invalid_instruction;
2236122413
22362 if (casted_op1->value.special == ConstValSpecialStatic &&
22363 casted_op2->value.special == ConstValSpecialStatic &&
22364 casted_result_ptr->value.special == ConstValSpecialStatic)
22414 if (instr_is_comptime(casted_op1) &&
22415 instr_is_comptime(casted_op2) &&
22416 instr_is_comptime(casted_result_ptr))
2236522417 {
22366 BigInt *op1_bigint = &casted_op1->value.data.x_bigint;
22367 BigInt *op2_bigint = &casted_op2->value.data.x_bigint;
22368 ConstExprValue *pointee_val = const_ptr_pointee(ira, ira->codegen, &casted_result_ptr->value, casted_result_ptr->source_node);
22418 ConstExprValue *op1_val = ir_resolve_const(ira, casted_op1, UndefBad);
22419 if (op1_val == nullptr)
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);
2236922434 if (pointee_val == nullptr)
2237022435 return ira->codegen->invalid_instruction;
2237122436 BigInt *dest_bigint = &pointee_val->data.x_bigint;
......@@ -22754,84 +22819,64 @@ static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruct
2275422819 AstNode *proto_node = instruction->base.source_node;
2275522820 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
2275722830 if (proto_node->data.fn_proto.auto_err_set) {
2275822831 ir_add_error(ira, &instruction->base,
2275922832 buf_sprintf("inferring error set of return type valid only for function definitions"));
2276022833 return ira->codegen->invalid_instruction;
2276122834 }
2276222835
22763 FnTypeId fn_type_id = {0};
22764 init_fn_type_id(&fn_type_id, proto_node, proto_node->data.fn_proto.params.length);
22836 size_t param_count = 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) {
22767 AstNode *param_node = proto_node->data.fn_proto.params.at(fn_type_id.next_param_index);
22840 for (size_t param_index = 0; param_index < param_count; param_index += 1) {
22841 AstNode *param_node = proto_node->data.fn_proto.params.at(param_index);
2276822842 assert(param_node->type == NodeTypeParamDecl);
2276922843
2277022844 bool param_is_var_args = param_node->data.param_decl.is_var_args;
2277122845 if (param_is_var_args) {
22772 if (fn_type_id.cc == CallingConventionC) {
22773 fn_type_id.param_count = fn_type_id.next_param_index;
22774 continue;
22775 } else if (fn_type_id.cc == CallingConventionUnspecified) {
22776 return ir_const_type(ira, &instruction->base, get_generic_fn_type(ira->codegen, &fn_type_id));
22846 if (proto_node->data.fn_proto.cc == CallingConventionC) {
22847 break;
22848 } else if (proto_node->data.fn_proto.cc == CallingConventionUnspecified) {
22849 lazy_fn_type->is_generic = true;
22850 return result;
2277722851 } else {
2277822852 zig_unreachable();
2277922853 }
2278022854 }
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) {
22785 param_info->type = nullptr;
22786 return ir_const_type(ira, &instruction->base, get_generic_fn_type(ira->codegen, &fn_type_id));
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;
22856 if (instruction->param_types[param_index] == nullptr) {
22857 lazy_fn_type->is_generic = true;
22858 return result;
2281522859 }
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;
2281722867 }
2281822868
2281922869 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)
2282122872 return ira->codegen->invalid_instruction;
2282222873 }
2282322874
22824 IrInstruction *return_type_value = instruction->return_type->child;
22825 fn_type_id.return_type = ir_resolve_type(ira, return_type_value);
22826 if (type_is_invalid(fn_type_id.return_type))
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 }
22875 lazy_fn_type->return_type = instruction->return_type->child;
22876 if (ir_resolve_const(ira, lazy_fn_type->return_type, LazyOk) == nullptr)
22877 return ira->codegen->invalid_instruction;
2283322878
22834 return ir_const_type(ira, &instruction->base, get_fn_type(ira->codegen, &fn_type_id));
22879 return result;
2283522880}
2283622881
2283722882static IrInstruction *ir_analyze_instruction_test_comptime(IrAnalyze *ira, IrInstructionTestComptime *instruction) {
......@@ -23218,7 +23263,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
2321823263 if (!val)
2321923264 return ira->codegen->invalid_instruction;
2322023265
23221 if (val->special == ConstValSpecialStatic) {
23266 if (value_is_comptime(val) && val->special != ConstValSpecialUndef) {
2322223267 bool is_addr_zero = val->data.x_ptr.special == ConstPtrSpecialNull ||
2322323268 (val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr &&
2322423269 val->data.x_ptr.data.hard_coded_addr.addr == 0);
......@@ -23258,6 +23303,12 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
2325823303
2325923304 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
2326123312 if (type_has_bits(dest_type) && !type_has_bits(src_type)) {
2326223313 ErrorMsg *msg = ir_add_error(ira, source_instr,
2326323314 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
2330923360}
2331023361
2331123362static 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);
2331323365 val->special = ConstValSpecialStatic;
23366 }
2331423367 assert(val->special == ConstValSpecialStatic);
2331523368 switch (val->type->id) {
2331623369 case ZigTypeIdInvalid:
......@@ -23500,7 +23553,7 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou
2350023553 BigInt bn;
2350123554 bigint_read_twos_complement(&bn, buf, codegen->builtin_types.entry_usize->data.integral.bit_count,
2350223555 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);
2350423557 return ErrorNone;
2350523558 }
2350623559 case ZigTypeIdArray:
......@@ -23693,7 +23746,7 @@ static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *sourc
2369323746 if (!val)
2369423747 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);
2369723750 if (!ptr_allows_addr_zero(ptr_type) && addr == 0) {
2369823751 ir_add_error(ira, source_instr,
2369923752 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,
2374623799 IrInstructionDeclRef *instruction)
2374723800{
2374823801 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)) {
2375023803 return ira->codegen->invalid_instruction;
23804 }
2375123805
2375223806 if (instruction->lval == LValPtr) {
2375323807 return ref_instruction;
......@@ -23795,53 +23849,32 @@ static IrInstruction *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstru
2379523849}
2379623850
2379723851static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstructionPtrType *instruction) {
23798 Error err;
23799 ZigType *child_type = ir_resolve_type(ira, instruction->child_type->child);
23800 if (type_is_invalid(child_type))
23801 return ira->codegen->invalid_instruction;
23852 IrInstruction *result = ir_const(ira, &instruction->base, ira->codegen->builtin_types.entry_type);
23853 result->value.special = ConstValSpecialLazy;
2380223854
23803 if (child_type->id == ZigTypeIdUnreachable) {
23804 ir_add_error(ira, &instruction->base, buf_sprintf("pointer to noreturn not allowed"));
23805 return ira->codegen->invalid_instruction;
23806 } else if (child_type->id == ZigTypeIdOpaque && instruction->ptr_len == PtrLenUnknown) {
23807 ir_add_error(ira, &instruction->base, buf_sprintf("unknown-length pointer to opaque"));
23855 LazyValuePtrType *lazy_ptr_type = allocate<LazyValuePtrType>(1);
23856 lazy_ptr_type->ira = ira;
23857 result->value.data.x_lazy = &lazy_ptr_type->base;
23858 lazy_ptr_type->base.id = LazyValueIdPtrType;
23859
23860 lazy_ptr_type->elem_type = instruction->child_type->child;
23861 if (ir_resolve_type_lazy(ira, lazy_ptr_type->elem_type) == nullptr)
2380823862 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;
2382423864 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)
2382623867 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;
2383623868 }
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,
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);
23877 return result;
2384523878}
2384623879
2384723880static IrInstruction *ir_analyze_instruction_align_cast(IrAnalyze *ira, IrInstructionAlignCast *instruction) {
......@@ -23954,7 +23987,7 @@ static IrInstruction *ir_analyze_instruction_tag_type(IrAnalyze *ira, IrInstruct
2395423987 return ira->codegen->invalid_instruction;
2395523988
2395623989 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)))
2395823991 return ira->codegen->invalid_instruction;
2395923992
2396023993 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
2510025133ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_exec,
2510125134 ZigType *expected_type, AstNode *expected_type_source_node)
2510225135{
25103 assert(!old_exec->invalid);
25136 assert(old_exec->first_err_trace_msg == nullptr);
2510425137 assert(expected_type == nullptr || !type_is_invalid(expected_type));
2510525138
2510625139 IrAnalyze *ira = allocate<IrAnalyze>(1);
......@@ -25147,6 +25180,18 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_
2514725180 old_instruction->child = new_instruction;
2514825181
2514925182 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 }
2515025195 return ira->codegen->builtin_types.entry_invalid;
2515125196 }
2515225197
......@@ -25158,7 +25203,15 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_
2515825203 ira->instruction_index += 1;
2515925204 }
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 }
2516225215 return ira->codegen->builtin_types.entry_invalid;
2516325216 } else if (ira->src_implicit_return_type_list.length == 0) {
2516425217 return codegen->builtin_types.entry_unreachable;
......@@ -25354,3 +25407,336 @@ bool ir_has_side_effects(IrInstruction *instruction) {
2535425407 }
2535525408 zig_unreachable();
2535625409}
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);
1616ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
1717 ZigType *expected_type, size_t *backward_branch_count, size_t *backward_branch_quota,
1818 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
2123ZigType *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutable *new_executable,
2224 ZigType *expected_type, AstNode *expected_type_source_node);
......@@ -28,6 +30,4 @@ ConstExprValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ConstExprVal
2830 AstNode *source_node);
2931const char *float_op_to_name(BuiltinFnId op, bool llvm_name);
3032
31void ir_add_analysis_trace(IrAnalyze *ira, ErrorMsg *err_msg, Buf *text);
32
3333#endif
src/os.cpp+15-15
......@@ -1125,29 +1125,27 @@ Error os_get_cwd(Buf *out_cwd) {
11251125#endif
11261126}
11271127
1128#if defined(ZIG_OS_WINDOWS)
11291128#define is_wprefix(s, prefix) \
11301129 (wcsncmp((s), (prefix), sizeof(prefix) / sizeof(WCHAR) - 1) == 0)
1131static bool is_stderr_cyg_pty(void) {
1132 HANDLE stderr_handle = GetStdHandle(STD_ERROR_HANDLE);
1133 if (stderr_handle == INVALID_HANDLE_VALUE)
1130bool ATTRIBUTE_MUST_USE os_is_cygwin_pty(int fd) {
1131#if defined(ZIG_OS_WINDOWS)
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) {
11341136 return false;
1137 }
11351138
11361139 int size = sizeof(FILE_NAME_INFO) + sizeof(WCHAR) * MAX_PATH;
1137 FILE_NAME_INFO *nameinfo;
11381140 WCHAR *p = NULL;
11391141
1140 // Cygwin/msys's pty is a pipe.
1141 if (GetFileType(stderr_handle) != FILE_TYPE_PIPE) {
1142 return 0;
1143 }
1144 nameinfo = (FILE_NAME_INFO *)allocate<char>(size);
1142 FILE_NAME_INFO *nameinfo = (FILE_NAME_INFO *)allocate<char>(size);
11451143 if (nameinfo == NULL) {
1146 return 0;
1144 return false;
11471145 }
11481146 // Check the name of the pipe:
11491147 // '\{cygwin,msys}-XXXXXXXXXXXXXXXX-ptyN-{from,to}-master'
1150 if (GetFileInformationByHandleEx(stderr_handle, FileNameInfo, nameinfo, size)) {
1148 if (GetFileInformationByHandleEx(handle, FileNameInfo, nameinfo, size)) {
11511149 nameinfo->FileName[nameinfo->FileNameLength / sizeof(WCHAR)] = L'\0';
11521150 p = nameinfo->FileName;
11531151 if (is_wprefix(p, L"\\cygwin-")) { /* Cygwin */
......@@ -1180,12 +1178,14 @@ static bool is_stderr_cyg_pty(void) {
11801178 }
11811179 free(nameinfo);
11821180 return (p != NULL);
1183}
1181#else
1182 return false;
11841183#endif
1184}
11851185
11861186bool os_stderr_tty(void) {
11871187#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));
11891189#elif defined(ZIG_OS_POSIX)
11901190 return isatty(STDERR_FILENO) != 0;
11911191#else
......@@ -1486,7 +1486,7 @@ WORD original_console_attributes = FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BL
14861486
14871487void os_stderr_set_color(TermColor color) {
14881488#if defined(ZIG_OS_WINDOWS)
1489 if (is_stderr_cyg_pty()) {
1489 if (os_stderr_tty()) {
14901490 set_color_posix(color);
14911491 return;
14921492 }
src/os.hpp+8
......@@ -11,6 +11,7 @@
1111#include "list.hpp"
1212#include "buffer.hpp"
1313#include "error.hpp"
14#include "target.hpp"
1415#include "zig_llvm.h"
1516#include "windows_sdk.h"
1617
......@@ -88,6 +89,11 @@ struct Termination {
8889#define OsFile int
8990#endif
9091
92#if defined(ZIG_OS_WINDOWS)
93#undef fileno
94#define fileno _fileno
95#endif
96
9197struct OsTimeStamp {
9298 uint64_t sec;
9399 uint64_t nsec;
......@@ -152,6 +158,8 @@ Error ATTRIBUTE_MUST_USE os_get_win32_ucrt_include_path(ZigWindowsSDK *sdk, Buf
152158Error ATTRIBUTE_MUST_USE os_get_win32_ucrt_lib_path(ZigWindowsSDK *sdk, Buf *output_buf, ZigLLVM_ArchType platform_type);
153159Error 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
155163Error ATTRIBUTE_MUST_USE os_self_exe_shared_libs(ZigList<Buf *> &paths);
156164
157165#endif
src/parser.cpp+5-3
......@@ -782,24 +782,26 @@ static AstNode *ast_parse_var_decl(ParseContext *pc) {
782782 return res;
783783}
784784
785// ContainerField <- IDENTIFIER (COLON TypeExpr)? (EQUAL Expr)?
785// ContainerField <- IDENTIFIER (COLON TypeExpr ByteAlign?)? (EQUAL Expr)?
786786static AstNode *ast_parse_container_field(ParseContext *pc) {
787787 Token *identifier = eat_token_if(pc, TokenIdSymbol);
788788 if (identifier == nullptr)
789789 return nullptr;
790790
791791 AstNode *type_expr = nullptr;
792 if (eat_token_if(pc, TokenIdColon) != nullptr)
792 if (eat_token_if(pc, TokenIdColon) != nullptr) {
793793 type_expr = ast_expect(pc, ast_parse_type_expr);
794 }
795 AstNode *align_expr = ast_parse_byte_align(pc);
794796 AstNode *expr = nullptr;
795797 if (eat_token_if(pc, TokenIdEq) != nullptr)
796798 expr = ast_expect(pc, ast_parse_expr);
797799
798
799800 AstNode *res = ast_create_node(pc, NodeTypeStructField, identifier);
800801 res->data.struct_field.name = token_buf(identifier);
801802 res->data.struct_field.type = type_expr;
802803 res->data.struct_field.value = expr;
804 res->data.struct_field.align_expr = align_expr;
803805 return res;
804806}
805807
src/target.cpp+14-1
......@@ -504,6 +504,16 @@ Error target_parse_glibc_version(ZigGLibCVersion *glibc_ver, const char *text) {
504504 return ErrorNone;
505505}
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
507517void get_native_target(ZigTarget *target) {
508518 // first zero initialize
509519 *target = {};
......@@ -518,6 +528,9 @@ void get_native_target(ZigTarget *target) {
518528 &target->abi,
519529 &oformat);
520530 target->os = get_zig_os_type(os_type);
531 if (target->os == OsWindows) {
532 target->abi = target_get_win32_abi();
533 }
521534 target->is_native = true;
522535 if (target->abi == ZigLLVM_UnknownEnvironment) {
523536 target->abi = target_default_abi(target->arch, target->os);
......@@ -1651,7 +1664,7 @@ ZigLLVM_EnvironmentType target_default_abi(ZigLLVM_ArchType arch, Os os) {
16511664 return ZigLLVM_GNU;
16521665 case OsUefi:
16531666 case OsWindows:
1654 return ZigLLVM_MSVC;
1667 return ZigLLVM_MSVC;
16551668 case OsLinux:
16561669 case OsWASI:
16571670 case OsEmscripten:
src/tokenizer.cpp+1-1
......@@ -841,7 +841,7 @@ void tokenize(Buf *buf, Tokenization *out) {
841841 case TokenizeStateSawAmpersand:
842842 switch (c) {
843843 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");
845845 break;
846846 case '=':
847847 set_token_id(&t, t.cur_tok, TokenIdBitAndEq);
src/zig_llvm.cpp+3-3
......@@ -15,9 +15,9 @@
1515
1616#include "zig_llvm.h"
1717
18#if __GNUC__ >= 8
18#if __GNUC__ >= 9
1919#pragma GCC diagnostic push
20#pragma GCC diagnostic ignored "-Wclass-memaccess"
20#pragma GCC diagnostic ignored "-Winit-list-lifetime"
2121#endif
2222
2323#include <llvm/Analysis/TargetLibraryInfo.h>
......@@ -50,7 +50,7 @@
5050
5151#include <lld/Common/Driver.h>
5252
53#if __GNUC__ >= 8
53#if __GNUC__ >= 9
5454#pragma GCC diagnostic pop
5555#endif
5656
std/array_list.zig+12-9
......@@ -6,20 +6,23 @@ const mem = std.mem;
66const Allocator = mem.Allocator;
77
88pub fn ArrayList(comptime T: type) type {
9 return AlignedArrayList(T, @alignOf(T));
9 return AlignedArrayList(T, null);
1010}
1111
12pub fn AlignedArrayList(comptime T: type, comptime A: u29) type {
12pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {
1313 return struct {
1414 const Self = @This();
1515
1616 /// Use toSlice instead of slicing this directly, because if you don't
1717 /// specify the end position of the slice, this will potentially give
1818 /// you uninitialized memory.
19 items: []align(A) T,
19 items: Slice,
2020 len: usize,
2121 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
2326 /// Deinitialize with `deinit` or use `toOwnedSlice`.
2427 pub fn init(allocator: *Allocator) Self {
2528 return Self{
......@@ -33,11 +36,11 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type {
3336 self.allocator.free(self.items);
3437 }
3538
36 pub fn toSlice(self: Self) []align(A) T {
39 pub fn toSlice(self: Self) Slice {
3740 return self.items[0..self.len];
3841 }
3942
40 pub fn toSliceConst(self: Self) []align(A) const T {
43 pub fn toSliceConst(self: Self) SliceConst {
4144 return self.items[0..self.len];
4245 }
4346
......@@ -69,7 +72,7 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type {
6972 /// ArrayList takes ownership of the passed in slice. The slice must have been
7073 /// allocated with `allocator`.
7174 /// 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 {
7376 return Self{
7477 .items = slice,
7578 .len = slice.len,
......@@ -78,7 +81,7 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type {
7881 }
7982
8083 /// 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 {
8285 const allocator = self.allocator;
8386 const result = allocator.shrink(self.items, self.len);
8487 self.* = init(allocator);
......@@ -93,7 +96,7 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type {
9396 self.items[n] = item;
9497 }
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 {
97100 try self.ensureCapacity(self.len + items.len);
98101 self.len += items.len;
99102
......@@ -141,7 +144,7 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type {
141144 return self.swapRemove(i);
142145 }
143146
144 pub fn appendSlice(self: *Self, items: []align(A) const T) !void {
147 pub fn appendSlice(self: *Self, items: SliceConst) !void {
145148 try self.ensureCapacity(self.len + items.len);
146149 mem.copy(T, self.items[self.len..], items);
147150 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);
269269fn Blake2b(comptime out_len: usize) type {
270270 return struct {
271271 const Self = @This();
272 const block_length = 128;
273 const digest_length = out_len / 8;
272 pub const block_length = 128;
273 pub const digest_length = out_len / 8;
274274
275275 const iv = [8]u64{
276276 0x6a09e667f3bcc908,
std/crypto/sha2.zig+2-2
......@@ -420,8 +420,8 @@ pub const Sha512 = Sha2_64(Sha512Params);
420420fn Sha2_64(comptime params: Sha2Params64) type {
421421 return struct {
422422 const Self = @This();
423 const block_length = 128;
424 const digest_length = params.out_len / 8;
423 pub const block_length = 128;
424 pub const digest_length = params.out_len / 8;
425425
426426 s: [8]u64,
427427 // 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 {
719719 Delete,
720720};
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
722732//pub const WatchEventError = error{
723733// UserResourceLimitReached,
724734// SystemResources,
......@@ -736,7 +746,7 @@ pub const WatchEventId = enum {
736746// file_table: FileTable,
737747// table_lock: event.Lock,
738748//
739// const FileTable = std.AutoHashMap([]const u8, *Put);
749// const FileTable = std.StringHashmap(*Put);
740750// const Put = struct {
741751// putter: anyframe,
742752// value_ptr: *V,
......@@ -755,8 +765,8 @@ pub const WatchEventId = enum {
755765// all_putters: std.atomic.Queue(anyframe),
756766// ref_count: std.atomic.Int(usize),
757767//
758// const DirTable = std.AutoHashMap([]const u8, *Dir);
759// const FileTable = std.AutoHashMap([]const u16, V);
768// const DirTable = std.StringHashMap(*Dir);
769// const FileTable = std.HashMap([]const u16, V, hashString, eqlString);
760770//
761771// const Dir = struct {
762772// putter: anyframe,
......@@ -772,7 +782,7 @@ pub const WatchEventId = enum {
772782// table_lock: event.Lock,
773783//
774784// const WdTable = std.AutoHashMap(i32, Dir);
775// const FileTable = std.AutoHashMap([]const u8, V);
785// const FileTable = std.StringHashMap(V);
776786//
777787// const Dir = struct {
778788// dirname: []const u8,
......@@ -780,7 +790,7 @@ pub const WatchEventId = enum {
780790// };
781791// };
782792//
783// const FileToHandle = std.AutoHashMap([]const u8, anyframe);
793// const FileToHandle = std.StringHashMap(anyframe);
784794//
785795// const Self = @This();
786796//
std/hash/auto_hash.zig+229-62
......@@ -1,11 +1,79 @@
11const std = @import("std");
22const builtin = @import("builtin");
3const assert = std.debug.assert;
34const mem = std.mem;
45const 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
674/// Provides generic hashing for any eligible type.
7/// Only hashes `key` itself, pointers are not followed.
8pub fn autoHash(hasher: var, key: var) void {
75/// Strategy is provided to determine if pointers should be followed or not.
76pub fn hash(hasher: var, key: var, comptime strat: HashStrategy) void {
977 const Key = @typeOf(key);
1078 switch (@typeInfo(Key)) {
1179 .NoReturn,
......@@ -26,35 +94,18 @@ pub fn autoHash(hasher: var, key: var) void {
2694 // TODO Check if the situation is better after #561 is resolved.
2795 .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)),
32 .Enum => autoHash(hasher, @enumToInt(key)),
33 .ErrorSet => autoHash(hasher, @errorToInt(key)),
34 .AnyFrame, .Fn => autoHash(hasher, @ptrToInt(key)),
99 .Bool => hash(hasher, @boolToInt(key), strat),
100 .Enum => hash(hasher, @enumToInt(key), strat),
101 .ErrorSet => hash(hasher, @errorToInt(key), strat),
102 .AnyFrame, .Fn => hash(hasher, @ptrToInt(key), strat),
35103
36 .Pointer => |info| switch (info.size) {
37 builtin.TypeInfo.Pointer.Size.One,
38 builtin.TypeInfo.Pointer.Size.Many,
39 builtin.TypeInfo.Pointer.Size.C,
40 => autoHash(hasher, @ptrToInt(key)),
104 .Pointer => @inlineCall(hashPointer, hasher, key, strat),
41105
42 builtin.TypeInfo.Pointer.Size.Slice => {
43 autoHash(hasher, key.ptr);
44 autoHash(hasher, key.len);
45 },
46 },
47
48 .Optional => if (key) |k| autoHash(hasher, k),
106 .Optional => if (key) |k| hash(hasher, k, strat),
49107
50 .Array => {
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 },
108 .Array => hashArray(hasher, key, strat),
58109
59110 .Vector => |info| {
60111 if (info.child.bit_count % 8 == 0) {
......@@ -67,7 +118,7 @@ pub fn autoHash(hasher: var, key: var) void {
67118 const array: [info.len]info.child = key;
68119 comptime var i: u32 = 0;
69120 inline while (i < info.len) : (i += 1) {
70 autoHash(hasher, array[i]);
121 hash(hasher, array[i], strat);
71122 }
72123 }
73124 },
......@@ -79,19 +130,19 @@ pub fn autoHash(hasher: var, key: var) void {
79130 inline for (info.fields) |field| {
80131 // We reuse the hash of the previous field as the seed for the
81132 // next one so that they're dependant.
82 autoHash(hasher, @field(key, field.name));
133 hash(hasher, @field(key, field.name), strat);
83134 }
84135 },
85136
86137 .Union => |info| blk: {
87138 if (info.tag_type) |tag_type| {
88139 const tag = meta.activeTag(key);
89 const s = autoHash(hasher, tag);
140 const s = hash(hasher, tag, strat);
90141 inline for (info.fields) |field| {
91142 const enum_field = field.enum_field.?;
92143 if (enum_field.value == @enumToInt(tag)) {
93 autoHash(hasher, @field(key, enum_field.name));
94 // TODO use a labelled break when it does not crash the compiler.
144 hash(hasher, @field(key, enum_field.name), strat);
145 // TODO use a labelled break when it does not crash the compiler. cf #2908
95146 // break :blk;
96147 return;
97148 }
......@@ -102,25 +153,102 @@ pub fn autoHash(hasher: var, key: var) void {
102153
103154 .ErrorUnion => blk: {
104155 const payload = key catch |err| {
105 autoHash(hasher, err);
156 hash(hasher, err, strat);
106157 break :blk;
107158 };
108 autoHash(hasher, payload);
159 hash(hasher, payload, strat);
109160 },
110161 }
111162}
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
113184const testing = std.testing;
114185const 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 {
117202 // Any hash could be used here, for testing autoHash.
118203 var hasher = Wyhash.init(0);
119 autoHash(&hasher, key);
204 hash(&hasher, key, .Deep);
120205 return hasher.final();
121206}
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" {
124252 // Allocate one array dynamically so that we're assured it is not merged
125253 // with the other by the optimization passes.
126254 const array1 = try std.heap.direct_allocator.create([6]u32);
......@@ -130,23 +258,62 @@ test "autoHash slice" {
130258 const a = array1[0..];
131259 const b = array2[0..];
132260 const c = array1[0..3];
133 testing.expect(testAutoHash(a) == testAutoHash(a));
134 testing.expect(testAutoHash(a) != testAutoHash(array1));
135 testing.expect(testAutoHash(a) != testAutoHash(b));
136 testing.expect(testAutoHash(a) != testAutoHash(c));
261 testing.expect(testHashDeep(a) == testHashDeep(a));
262 testing.expect(testHashDeep(a) == testHashDeep(array1));
263 testing.expect(testHashDeep(a) == testHashDeep(b));
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));
137304}
138305
139test "testAutoHash optional" {
306test "testHash optional" {
140307 const a: ?u32 = 123;
141308 const b: ?u32 = null;
142 testing.expectEqual(testAutoHash(a), testAutoHash(u32(123)));
143 testing.expect(testAutoHash(a) != testAutoHash(b));
144 testing.expectEqual(testAutoHash(b), 0);
309 testing.expectEqual(testHash(a), testHash(u32(123)));
310 testing.expect(testHash(a) != testHash(b));
311 testing.expectEqual(testHash(b), 0);
145312}
146313
147test "testAutoHash array" {
314test "testHash array" {
148315 const a = [_]u32{ 1, 2, 3 };
149 const h = testAutoHash(a);
316 const h = testHash(a);
150317 var hasher = Wyhash.init(0);
151318 autoHash(&hasher, u32(1));
152319 autoHash(&hasher, u32(2));
......@@ -154,14 +321,14 @@ test "testAutoHash array" {
154321 testing.expectEqual(h, hasher.final());
155322}
156323
157test "testAutoHash struct" {
324test "testHash struct" {
158325 const Foo = struct {
159326 a: u32 = 1,
160327 b: u32 = 2,
161328 c: u32 = 3,
162329 };
163330 const f = Foo{};
164 const h = testAutoHash(f);
331 const h = testHash(f);
165332 var hasher = Wyhash.init(0);
166333 autoHash(&hasher, u32(1));
167334 autoHash(&hasher, u32(2));
......@@ -169,7 +336,7 @@ test "testAutoHash struct" {
169336 testing.expectEqual(h, hasher.final());
170337}
171338
172test "testAutoHash union" {
339test "testHash union" {
173340 const Foo = union(enum) {
174341 A: u32,
175342 B: f32,
......@@ -179,24 +346,24 @@ test "testAutoHash union" {
179346 const a = Foo{ .A = 18 };
180347 var b = Foo{ .B = 12.34 };
181348 const c = Foo{ .C = 18 };
182 testing.expect(testAutoHash(a) == testAutoHash(a));
183 testing.expect(testAutoHash(a) != testAutoHash(b));
184 testing.expect(testAutoHash(a) != testAutoHash(c));
349 testing.expect(testHash(a) == testHash(a));
350 testing.expect(testHash(a) != testHash(b));
351 testing.expect(testHash(a) != testHash(c));
185352
186353 b = Foo{ .A = 18 };
187 testing.expect(testAutoHash(a) == testAutoHash(b));
354 testing.expect(testHash(a) == testHash(b));
188355}
189356
190test "testAutoHash vector" {
357test "testHash vector" {
191358 const a: @Vector(4, u32) = [_]u32{ 1, 2, 3, 4 };
192359 const b: @Vector(4, u32) = [_]u32{ 1, 2, 3, 5 };
193360 const c: @Vector(4, u31) = [_]u31{ 1, 2, 3, 4 };
194 testing.expect(testAutoHash(a) == testAutoHash(a));
195 testing.expect(testAutoHash(a) != testAutoHash(b));
196 testing.expect(testAutoHash(a) != testAutoHash(c));
361 testing.expect(testHash(a) == testHash(a));
362 testing.expect(testHash(a) != testHash(b));
363 testing.expect(testHash(a) != testHash(c));
197364}
198365
199test "testAutoHash error union" {
366test "testHash error union" {
200367 const Errors = error{Test};
201368 const Foo = struct {
202369 a: u32 = 1,
......@@ -205,7 +372,7 @@ test "testAutoHash error union" {
205372 };
206373 const f = Foo{};
207374 const g: Errors!Foo = Errors.Test;
208 testing.expect(testAutoHash(f) != testAutoHash(g));
209 testing.expect(testAutoHash(f) == testAutoHash(Foo{}));
210 testing.expect(testAutoHash(g) == testAutoHash(Errors.Test));
375 testing.expect(testHash(f) != testHash(g));
376 testing.expect(testHash(f) == testHash(Foo{}));
377 testing.expect(testHash(g) == testHash(Errors.Test));
211378}
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;
1010const testing = std.testing;
1111
1212pub const Polynomial = struct {
13 const IEEE = 0xedb88320;
14 const Castagnoli = 0x82f63b78;
15 const Koopman = 0xeb31d82e;
13 pub const IEEE = 0xedb88320;
14 pub const Castagnoli = 0x82f63b78;
15 pub const Koopman = 0xeb31d82e;
1616};
1717
1818// 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 {
2121 return SipHash(u128, c_rounds, d_rounds);
2222}
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 {
2525 assert(T == u64 or T == u128);
2626 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)
3434 v1: u64,
3535 v2: u64,
3636 v3: u64,
37
38 // streaming cache
39 buf: [8]u8,
40 buf_len: usize,
4137 msg_len: u8,
4238
4339 pub fn init(key: []const u8) Self {
......@@ -51,9 +47,6 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize)
5147 .v1 = k1 ^ 0x646f72616e646f6d,
5248 .v2 = k0 ^ 0x6c7967656e657261,
5349 .v3 = k1 ^ 0x7465646279746573,
54
55 .buf = undefined,
56 .buf_len = 0,
5750 .msg_len = 0,
5851 };
5952
......@@ -64,73 +57,66 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize)
6457 return d;
6558 }
6659
67 pub fn update(d: *Self, b: []const u8) void {
68 var off: usize = 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 }
60 pub fn update(self: *Self, b: []const u8) void {
61 std.debug.assert(b.len % 8 == 0);
7762
78 // Full middle blocks.
79 while (off + 8 <= b.len) : (off += 8) {
80 d.round(b[off .. off + 8]);
63 var off: usize = 0;
64 while (off < b.len) : (off += 8) {
65 @inlineCall(self.round, b[off .. off + 8]);
8166 }
8267
83 // Remainder for next pass.
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);
68 self.msg_len +%= @truncate(u8, b.len);
8769 }
8870
89 pub fn final(d: *Self) T {
90 // Padding
91 mem.set(u8, d.buf[d.buf_len..], 0);
92 d.buf[7] = d.msg_len;
93 d.round(d.buf[0..]);
71 pub fn final(self: *Self, b: []const u8) T {
72 std.debug.assert(b.len < 8);
73
74 self.msg_len +%= @truncate(u8, b.len);
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
9581 if (T == u128) {
96 d.v2 ^= 0xee;
82 self.v2 ^= 0xee;
9783 } else {
98 d.v2 ^= 0xff;
84 self.v2 ^= 0xff;
9985 }
10086
10187 comptime var i: usize = 0;
10288 inline while (i < d_rounds) : (i += 1) {
103 @inlineCall(sipRound, d);
89 @inlineCall(sipRound, self);
10490 }
10591
106 const b1 = d.v0 ^ d.v1 ^ d.v2 ^ d.v3;
92 const b1 = self.v0 ^ self.v1 ^ self.v2 ^ self.v3;
10793 if (T == u64) {
10894 return b1;
10995 }
11096
111 d.v1 ^= 0xdd;
97 self.v1 ^= 0xdd;
11298
11399 comptime var j: usize = 0;
114100 inline while (j < d_rounds) : (j += 1) {
115 @inlineCall(sipRound, d);
101 @inlineCall(sipRound, self);
116102 }
117103
118 const b2 = d.v0 ^ d.v1 ^ d.v2 ^ d.v3;
104 const b2 = self.v0 ^ self.v1 ^ self.v2 ^ self.v3;
119105 return (u128(b2) << 64) | b1;
120106 }
121107
122 fn round(d: *Self, b: []const u8) void {
108 fn round(self: *Self, b: []const u8) void {
123109 assert(b.len == 8);
124110
125111 const m = mem.readIntSliceLittle(u64, b[0..]);
126 d.v3 ^= m;
112 self.v3 ^= m;
127113
128114 comptime var i: usize = 0;
129115 inline while (i < c_rounds) : (i += 1) {
130 @inlineCall(sipRound, d);
116 @inlineCall(sipRound, self);
131117 }
132118
133 d.v0 ^= m;
119 self.v0 ^= m;
134120 }
135121
136122 fn sipRound(d: *Self) void {
......@@ -151,9 +137,61 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize)
151137 }
152138
153139 pub fn hash(key: []const u8, input: []const u8) T {
140 const aligned_len = input.len - (input.len % 8);
141
154142 var c = Self.init(key);
155 c.update(input);
156 return c.final();
143 @inlineCall(c.update, input[0..aligned_len]);
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);
157195 }
158196 };
159197}
......@@ -237,7 +275,7 @@ test "siphash64-2-4 sanity" {
237275 buffer[i] = @intCast(u8, i);
238276
239277 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);
241279 }
242280}
243281
......@@ -316,6 +354,30 @@ test "siphash128-2-4 sanity" {
316354 buffer[i] = @intCast(u8, i);
317355
318356 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);
320382 }
321383}
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{
1010};
1111
1212fn 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]);
1415}
1516
1617fn read_8bytes_swapped(data: []const u8) u64 {
......@@ -31,18 +32,21 @@ fn mix1(a: u64, b: u64, seed: u64) u64 {
3132 return mum(a ^ seed ^ primes[2], b ^ seed ^ primes[3]);
3233}
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 {
3539 seed: u64,
3640 msg_len: usize,
3741
38 pub fn init(seed: u64) Wyhash {
39 return Wyhash{
42 pub fn init(seed: u64) WyhashStateless {
43 return WyhashStateless{
4044 .seed = seed,
4145 .msg_len = 0,
4246 };
4347 }
4448
45 fn round(self: *Wyhash, b: []const u8) void {
49 fn round(self: *WyhashStateless, b: []const u8) void {
4650 std.debug.assert(b.len == 32);
4751
4852 self.seed = mix0(
......@@ -56,12 +60,25 @@ pub const Wyhash = struct {
5660 );
5761 }
5862
59 fn partial(self: *Wyhash, b: []const u8) void {
60 const rem_key = b;
61 const rem_len = b.len;
63 pub fn update(self: *WyhashStateless, b: []const u8) void {
64 std.debug.assert(b.len % 32 == 0);
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;
64 seed = switch (@intCast(u5, rem_len)) {
71 self.msg_len += b.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) {
6582 0 => seed,
6683 1 => mix0(read_bytes(1, rem_key), primes[4], seed),
6784 2 => mix0(read_bytes(2, rem_key), primes[4], seed),
......@@ -95,34 +112,70 @@ pub const Wyhash = struct {
95112 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),
96113 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),
97114 };
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 };
99143 }
100144
101145 pub fn update(self: *Wyhash, b: []const u8) void {
102146 var off: usize = 0;
103147
104 // Full middle blocks.
105 while (off + 32 <= b.len) : (off += 32) {
106 @inlineCall(self.round, b[off .. off + 32]);
148 if (self.buf_len != 0 and self.buf_len + b.len >= 32) {
149 off += 32 - self.buf_len;
150 mem.copy(u8, self.buf[self.buf_len..], b[0..off]);
151 self.state.update(self.buf[0..]);
152 self.buf_len = 0;
107153 }
108154
109 self.partial(b[off..]);
110 self.msg_len += b.len;
155 const remain_len = b.len - off;
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);
111161 }
112162
113163 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);
115169 }
116170
117171 pub fn hash(seed: u64, input: []const u8) u64 {
118 var c = Wyhash.init(seed);
119 c.update(input);
120 return c.final();
172 return WyhashStateless.hash(seed, input);
121173 }
122174};
123175
176const expectEqual = std.testing.expectEqual;
177
124178test "test vectors" {
125 const expectEqual = std.testing.expectEqual;
126179 const hash = Wyhash.hash;
127180
128181 expectEqual(hash(0, ""), 0x0);
......@@ -133,3 +186,46 @@ test "test vectors" {
133186 expectEqual(hash(5, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"), 0x602a1894d3bbfe7f);
134187 expectEqual(hash(6, "12345678901234567890123456789012345678901234567890123456789012345678901234567890"), 0x829e9c148b75970e);
135188}
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 {
1717 return HashMap(K, V, getAutoHashFn(K), getAutoEqlFn(K));
1818}
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
2035pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u32, comptime eql: fn (a: K, b: K) bool) type {
2136 return struct {
2237 entries: []Entry,
std/http/headers.zig+1-11
......@@ -102,19 +102,9 @@ test "HeaderEntry" {
102102 testing.expectEqualSlices(u8, "x", e.value);
103103}
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
115105const HeaderList = std.ArrayList(HeaderEntry);
116106const HeaderIndexList = std.ArrayList(usize);
117const HeaderIndex = std.HashMap([]const u8, HeaderIndexList, stringHash, stringEql);
107const HeaderIndex = std.StringHashMap(HeaderIndexList);
118108
119109pub const Headers = struct {
120110 // 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{
6565 InvalidUtf8,
6666
6767 /// On Windows, file paths cannot contain these characters:
68 /// '/', '*', '?', '"', '<', '>', '|'
68 /// '*', '?', '"', '<', '>', '|', and '/' (when the ABI is not GNU)
6969 BadPathName,
7070
7171 Unexpected,
......@@ -836,11 +836,10 @@ pub fn sliceToPrefixedSuffixedFileW(s: []const u8, comptime suffix: []const u16)
836836 // > converting the name to an NT-style name, except when using the "\\?\"
837837 // > prefix as detailed in the following sections.
838838 // 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.
841839 for (s) |byte| {
842840 switch (byte) {
843 '/', '*', '?', '"', '<', '>', '|' => return error.BadPathName,
841 '*', '?', '"', '<', '>', '|' => return error.BadPathName,
842 '/' => if (builtin.abi == .msvc) return error.BadPathName,
844843 else => {},
845844 }
846845 }
std/std.zig+1
......@@ -17,6 +17,7 @@ pub const SinglyLinkedList = @import("linked_list.zig").SinglyLinkedList;
1717pub const StaticallyInitializedMutex = @import("statically_initialized_mutex.zig").StaticallyInitializedMutex;
1818pub const SegmentedList = @import("segmented_list.zig").SegmentedList;
1919pub const SpinLock = @import("spinlock.zig").SpinLock;
20pub const StringHashMap = @import("hash_map.zig").StringHashMap;
2021pub const ChildProcess = @import("child_process.zig").ChildProcess;
2122pub const TailQueue = @import("linked_list.zig").TailQueue;
2223pub const Thread = @import("thread.zig").Thread;
std/zig/ast.zig+1
......@@ -761,6 +761,7 @@ pub const Node = struct {
761761 name_token: TokenIndex,
762762 type_expr: ?*Node,
763763 value_expr: ?*Node,
764 align_expr: ?*Node,
764765
765766 pub fn iterate(self: *ContainerField, index: usize) ?*Node {
766767 var i = index;
std/zig/parse.zig+9-6
......@@ -380,16 +380,18 @@ fn parseVarDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
380380 return &node.base;
381381}
382382
383/// ContainerField <- IDENTIFIER (COLON TypeExpr)? (EQUAL Expr)?
383/// ContainerField <- IDENTIFIER (COLON TypeExpr ByteAlign?)? (EQUAL Expr)?
384384fn parseContainerField(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
385385 const name_token = eatToken(it, .Identifier) orelse return null;
386386
387 const type_expr = if (eatToken(it, .Colon)) |_|
388 try expectNode(arena, it, tree, parseTypeExpr, AstError{
387 var align_expr: ?*Node = null;
388 var type_expr: ?*Node = null;
389 if (eatToken(it, .Colon)) |_| {
390 type_expr = try expectNode(arena, it, tree, parseTypeExpr, AstError{
389391 .ExpectedTypeExpr = AstError.ExpectedTypeExpr{ .token = it.index },
390 })
391 else
392 null;
392 });
393 align_expr = try parseByteAlign(arena, it, tree);
394 }
393395
394396 const value_expr = if (eatToken(it, .Equal)) |_|
395397 try expectNode(arena, it, tree, parseExpr, AstError{
......@@ -406,6 +408,7 @@ fn parseContainerField(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No
406408 .name_token = name_token,
407409 .type_expr = type_expr,
408410 .value_expr = value_expr,
411 .align_expr = align_expr,
409412 };
410413 return &node.base;
411414}
std/zig/parser_test.zig+120-1
......@@ -166,6 +166,15 @@ test "zig fmt: doc comments on param decl" {
166166 );
167167}
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
169178test "zig fmt: preserve space between async fn definitions" {
170179 try testCanonical(
171180 \\async fn a() void {}
......@@ -201,6 +210,103 @@ test "zig fmt: comment to disable/enable zig fmt" {
201210 );
202211}
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
204310test "zig fmt: pointer of unknown length" {
205311 try testCanonical(
206312 \\fn foo(ptr: [*]u8) void {}
......@@ -2269,7 +2375,6 @@ test "zig fmt: if type expr" {
22692375 \\
22702376 );
22712377}
2272
22732378test "zig fmt: file ends with struct field" {
22742379 try testTransform(
22752380 \\a: bool
......@@ -2279,6 +2384,20 @@ test "zig fmt: file ends with struct field" {
22792384 );
22802385}
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
22822401test "zig fmt: comments at several places in struct init" {
22832402 try testTransform(
22842403 \\var bar = Bar{
std/zig/render.zig+115-36
......@@ -89,41 +89,98 @@ fn renderRoot(
8989 var it = tree.root_node.decls.iterator(0);
9090 while (true) {
9191 var decl = (it.next() orelse return).*;
92 // look for zig fmt: off comment
93 var start_token_index = decl.firstToken();
94 zig_fmt_loop: while (start_token_index != 0) {
95 start_token_index -= 1;
96 const start_token = tree.tokens.at(start_token_index);
97 switch (start_token.id) {
92
93 // This loop does the following:
94 //
95 // - Iterates through line/doc comment tokens that precedes the current
96 // decl.
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) {
98112 Token.Id.LineComment => {},
99 Token.Id.DocComment => continue,
113 Token.Id.DocComment => {
114 copy_start_token_index = token_index;
115 continue;
116 },
100117 else => break,
101118 }
102 if (mem.eql(u8, mem.trim(u8, tree.tokenSlicePtr(start_token)[2..], " "), "zig fmt: off")) {
103 var end_token_index = start_token_index;
104 while (true) {
105 end_token_index += 1;
106 const end_token = tree.tokens.at(end_token_index);
107 switch (end_token.id) {
119
120 if (mem.eql(u8, mem.trim(u8, tree.tokenSlicePtr(token)[2..], " "), "zig fmt: off")) {
121 if (!found_fmt_directive) {
122 fmt_active = false;
123 found_fmt_directive = true;
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) {
108152 Token.Id.LineComment => {},
109 Token.Id.Eof => {
110 const start = tree.tokens.at(start_token_index + 1).start;
111 try copyFixingWhitespace(stream, tree.source[start..]);
112 return;
113 },
153 Token.Id.Eof => unreachable,
114154 else => continue,
115155 }
116 if (mem.eql(u8, mem.trim(u8, tree.tokenSlicePtr(end_token)[2..], " "), "zig fmt: on")) {
117 const start = tree.tokens.at(start_token_index + 1).start;
118 try copyFixingWhitespace(stream, tree.source[start..end_token.end]);
119 try stream.writeByte('\n');
120 while (tree.tokens.at(decl.firstToken()).start < end_token.end) {
121 decl = (it.next() orelse return).*;
122 }
123 break :zig_fmt_loop;
156 if (mem.eql(u8, mem.trim(u8, tree.tokenSlicePtr(token)[2..], " "), "zig fmt: on")) {
157 fmt_active = true;
158 } else if (mem.eql(u8, mem.trim(u8, tree.tokenSlicePtr(token)[2..], " "), "zig fmt: off")) {
159 fmt_active = false;
124160 }
125161 }
126162 }
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]);
127184 }
128185
129186 try renderTopLevelDecl(allocator, stream, tree, 0, &start_col, decl);
......@@ -206,7 +263,20 @@ fn renderTopLevelDecl(allocator: *mem.Allocator, stream: var, tree: *ast.Tree, i
206263 } else if (field.type_expr != null and field.value_expr == null) {
207264 try renderToken(tree, stream, field.name_token, indent, start_col, Space.None); // name
208265 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
210280 } else if (field.type_expr == null and field.value_expr != null) {
211281 try renderToken(tree, stream, field.name_token, indent, start_col, Space.Space); // name
212282 try renderToken(tree, stream, tree.nextToken(field.name_token), indent, start_col, Space.Space); // =
......@@ -1924,15 +1994,24 @@ fn renderTokenOffset(
19241994 }
19251995 }
19261996
1927 const comment_is_empty = mem.trimRight(u8, tree.tokenSlicePtr(next_token), " ").len == 2;
1928 if (comment_is_empty) {
1929 switch (space) {
1930 Space.Newline => {
1931 try stream.writeByte('\n');
1932 start_col.* = 0;
1933 return;
1934 },
1935 else => {},
1997 while (true) {
1998 const comment_is_empty = mem.trimRight(u8, tree.tokenSlicePtr(next_token), " ").len == 2;
1999 if (comment_is_empty) {
2000 switch (space) {
2001 Space.Newline => {
2002 offset += 1;
2003 token = next_token;
2004 next_token = tree.tokens.at(token_index + offset);
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;
19362015 }
19372016 }
19382017
test/compile_errors.zig+89-44
......@@ -2,6 +2,51 @@ const tests = @import("tests.zig");
22const builtin = @import("builtin");
33
44pub 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
550 cases.addCase(x: {
651 var tc = cases.create("variable in inline assembly template cannot be found",
752 \\export fn entry() void {
......@@ -10,7 +55,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
1055 \\ : [bar] "=r" (-> usize)
1156 \\ );
1257 \\}
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");
1459 tc.target = tests.Target{
1560 .Cross = tests.CrossTarget{
1661 .arch = .x86_64,
......@@ -53,8 +98,8 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
5398 \\}
5499 ,
55100 "tmp.zig:8:1: error: '@Frame(rangeSum)' depends on itself",
56 "tmp.zig:15:33: note: when analyzing type '@Frame(rangeSumIndirect)' here",
57 "tmp.zig:26:25: note: when analyzing type '@Frame(rangeSum)' here",
101 "tmp.zig:15:33: note: when analyzing type '@Frame(rangeSum)' here",
102 "tmp.zig:26:25: note: when analyzing type '@Frame(rangeSumIndirect)' here",
58103 );
59104
60105 cases.add(
......@@ -245,7 +290,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
245290 ,
246291 "tmp.zig:4:1: error: unable to determine async function frame of 'amain'",
247292 "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",
249294 );
250295
251296 cases.add(
......@@ -258,7 +303,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
258303 \\}
259304 ,
260305 "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",
262307 );
263308
264309 cases.add(
......@@ -404,7 +449,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
404449 \\ const foo: Foo = undefined;
405450 \\}
406451 ,
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",
408453 );
409454
410455 cases.add(
......@@ -470,7 +515,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
470515 );
471516
472517 cases.add(
473 "Generic function where return type is self-referenced",
518 "generic function where return type is self-referenced",
474519 \\fn Foo(comptime T: type) Foo(T) {
475520 \\ return struct{ x: T };
476521 \\}
......@@ -481,7 +526,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
481526 \\}
482527 ,
483528 "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",
485530 );
486531
487532 cases.add(
......@@ -645,7 +690,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
645690 \\const A = struct { a : A, };
646691 \\export fn entry() usize { return @sizeOf(A); }
647692 ,
648 "tmp.zig:1:11: error: struct 'A' contains itself",
693 "tmp.zig:1:11: error: struct 'A' depends on itself",
649694 );
650695
651696 cases.add(
......@@ -655,7 +700,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
655700 \\const C = struct { a : A, };
656701 \\export fn entry() usize { return @sizeOf(A); }
657702 ,
658 "tmp.zig:1:11: error: struct 'A' contains itself",
703 "tmp.zig:1:11: error: struct 'A' depends on itself",
659704 );
660705
661706 cases.add(
......@@ -670,7 +715,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
670715 \\ return @sizeOf(@typeOf(foo.x));
671716 \\}
672717 ,
673 "tmp.zig:1:13: error: struct 'Foo' contains itself",
718 "tmp.zig:1:13: error: struct 'Foo' depends on itself",
674719 "tmp.zig:8:28: note: referenced here",
675720 );
676721
......@@ -689,7 +734,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
689734 \\}
690735 ,
691736 "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",
693738 "tmp.zig:10:21: note: referenced here",
694739 );
695740
......@@ -703,7 +748,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
703748 \\ var s: Foo = Foo.E;
704749 \\}
705750 ,
706 "tmp.zig:1:17: error: 'Foo' depends on itself",
751 "tmp.zig:1:17: error: enum 'Foo' depends on itself",
707752 );
708753
709754 cases.add(
......@@ -866,7 +911,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
866911 break :x tc;
867912 });
868913
869 cases.addTest(
914 cases.add(
870915 "export generic function",
871916 \\export fn foo(num: var) i32 {
872917 \\ return 0;
......@@ -875,17 +920,17 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
875920 "tmp.zig:1:15: error: parameter of type 'var' not allowed in function with calling convention 'ccc'",
876921 );
877922
878 cases.addTest(
923 cases.add(
879924 "C pointer to c_void",
880925 \\export fn a() void {
881926 \\ var x: *c_void = undefined;
882927 \\ var y: [*c]c_void = x;
883928 \\}
884929 ,
885 "tmp.zig:3:12: error: C pointers cannot point opaque types",
930 "tmp.zig:3:16: error: C pointers cannot point opaque types",
886931 );
887932
888 cases.addTest(
933 cases.add(
889934 "directly embedding opaque type in struct and union",
890935 \\const O = @OpaqueType();
891936 \\const Foo = struct {
......@@ -906,7 +951,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
906951 "tmp.zig:7:10: error: opaque types have unknown size and therefore cannot be directly embedded in unions",
907952 );
908953
909 cases.addTest(
954 cases.add(
910955 "implicit cast between C pointer and Zig pointer - bad const/align/child",
911956 \\export fn a() void {
912957 \\ var x: [*c]u8 = undefined;
......@@ -942,7 +987,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
942987 "tmp.zig:23:22: error: expected type '[*c]u32', found '*u8'",
943988 );
944989
945 cases.addTest(
990 cases.add(
946991 "implicit casting null c pointer to zig pointer",
947992 \\comptime {
948993 \\ var c_ptr: [*c]u8 = 0;
......@@ -952,7 +997,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
952997 "tmp.zig:3:24: error: null pointer casted to type '*u8'",
953998 );
954999
955 cases.addTest(
1000 cases.add(
9561001 "implicit casting undefined c pointer to zig pointer",
9571002 \\comptime {
9581003 \\ var c_ptr: [*c]u8 = undefined;
......@@ -962,7 +1007,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
9621007 "tmp.zig:3:24: error: use of undefined value here causes undefined behavior",
9631008 );
9641009
965 cases.addTest(
1010 cases.add(
9661011 "implicit casting C pointers which would mess up null semantics",
9671012 \\export fn entry() void {
9681013 \\ var slice: []const u8 = "aoeu";
......@@ -987,7 +1032,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
9871032 "tmp.zig:13:35: note: mutable '[*c]const u8' allows illegal null values stored to type '[*]u8'",
9881033 );
9891034
990 cases.addTest(
1035 cases.add(
9911036 "implicit casting too big integers to C pointers",
9921037 \\export fn a() void {
9931038 \\ var ptr: [*c]u8 = (1 << 64) + 1;
......@@ -1001,14 +1046,14 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
10011046 "tmp.zig:6:23: error: integer type 'u65' too big for implicit @intToPtr to type '[*c]u8'",
10021047 );
10031048
1004 cases.addTest(
1049 cases.add(
10051050 "C pointer pointing to non C ABI compatible type or has align attr",
10061051 \\const Foo = struct {};
10071052 \\export fn a() void {
10081053 \\ const T = [*c]Foo;
10091054 \\}
10101055 ,
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'",
10121057 );
10131058
10141059 cases.addCase(x: {
......@@ -1029,7 +1074,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
10291074 break :x tc;
10301075 });
10311076
1032 cases.addTest(
1077 cases.add(
10331078 "assign to invalid dereference",
10341079 \\export fn entry() void {
10351080 \\ 'a'.* = 1;
......@@ -1038,7 +1083,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
10381083 "tmp.zig:2:8: error: attempt to dereference non-pointer type 'comptime_int'",
10391084 );
10401085
1041 cases.addTest(
1086 cases.add(
10421087 "take slice of invalid dereference",
10431088 \\export fn entry() void {
10441089 \\ const x = 'a'.*[0..];
......@@ -1047,7 +1092,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
10471092 "tmp.zig:2:18: error: attempt to dereference non-pointer type 'comptime_int'",
10481093 );
10491094
1050 cases.addTest(
1095 cases.add(
10511096 "@truncate undefined value",
10521097 \\export fn entry() void {
10531098 \\ var z = @truncate(u8, u16(undefined));
......@@ -1091,7 +1136,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
10911136 \\ return 5678;
10921137 \\}
10931138 ,
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",
10951140 );
10961141
10971142 cases.add(
......@@ -1935,7 +1980,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
19351980 "unknown length pointer to opaque",
19361981 \\export const T = [*]@OpaqueType();
19371982 ,
1938 "tmp.zig:1:18: error: unknown-length pointer to opaque",
1983 "tmp.zig:1:21: error: unknown-length pointer to opaque",
19391984 );
19401985
19411986 cases.add(
......@@ -2924,7 +2969,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
29242969 \\fn a() *noreturn {}
29252970 \\export fn entry() void { _ = a(); }
29262971 ,
2927 "tmp.zig:1:8: error: pointer to noreturn not allowed",
2972 "tmp.zig:1:9: error: pointer to noreturn not allowed",
29282973 );
29292974
29302975 cases.add(
......@@ -3596,7 +3641,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
35963641 );
35973642
35983643 cases.add(
3599 "non constant expression in array size outside function",
3644 "non constant expression in array size",
36003645 \\const Foo = struct {
36013646 \\ y: [get()]u8,
36023647 \\};
......@@ -3606,8 +3651,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
36063651 \\export fn entry() usize { return @sizeOf(@typeOf(Foo)); }
36073652 ,
36083653 "tmp.zig:5:25: error: unable to evaluate constant expression",
3609 "tmp.zig:2:12: note: called from here",
3610 "tmp.zig:2:8: note: called from here",
3654 "tmp.zig:2:12: note: referenced here",
36113655 );
36123656
36133657 cases.add(
......@@ -3701,7 +3745,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
37013745 \\export fn entry() usize { return @sizeOf(@typeOf(y)); }
37023746 ,
37033747 "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",
37053749 );
37063750
37073751 cases.add(
......@@ -4133,7 +4177,8 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
41334177 \\export fn entry() usize { return @sizeOf(@typeOf(seventh_fib_number)); }
41344178 ,
41354179 "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",
41374182 );
41384183
41394184 cases.add(
......@@ -4174,7 +4219,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
41744219 \\export fn entry() usize { return @sizeOf(@typeOf(a)); }
41754220 ,
41764221 "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",
41784223 );
41794224
41804225 cases.add(
......@@ -4257,7 +4302,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
42574302 \\export fn entry() usize { return @sizeOf(@typeOf(y)); }
42584303 ,
42594304 "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",
42614306 );
42624307
42634308 cases.add(
......@@ -4270,7 +4315,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
42704315 \\export fn entry() usize { return @sizeOf(@typeOf(y)); }
42714316 ,
42724317 "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",
42744319 );
42754320
42764321 cases.add(
......@@ -4283,7 +4328,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
42834328 \\export fn entry() usize { return @sizeOf(@typeOf(y)); }
42844329 ,
42854330 "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",
42874332 );
42884333
42894334 cases.add(
......@@ -4296,7 +4341,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
42964341 \\export fn entry() usize { return @sizeOf(@typeOf(y)); }
42974342 ,
42984343 "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",
43004345 );
43014346
43024347 cases.add(
......@@ -4388,7 +4433,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
43884433 \\}
43894434 ,
43904435 "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",
43924437 );
43934438
43944439 cases.add(
......@@ -4717,7 +4762,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
47174762 \\}
47184763 ,
47194764 "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",
47214766 );
47224767
47234768 cases.add(
......@@ -5864,7 +5909,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
58645909 \\}
58655910 ,
58665911 "tmp.zig:4:25: error: aoeu",
5867 "tmp.zig:1:36: note: called from here",
5912 "tmp.zig:1:36: note: referenced here",
58685913 "tmp.zig:12:20: note: referenced here",
58695914 );
58705915
......@@ -5939,7 +5984,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
59395984 \\ var x: MultipleChoice = undefined;
59405985 \\}
59415986 ,
5942 "tmp.zig:2:14: error: non-enum union field assignment",
5987 "tmp.zig:2:14: error: untagged union field assignment",
59435988 "tmp.zig:1:24: note: consider 'union(enum)' here",
59445989 );
59455990
test/stage1/behavior.zig+4
......@@ -15,6 +15,7 @@ comptime {
1515 _ = @import("behavior/bugs/1111.zig");
1616 _ = @import("behavior/bugs/1120.zig");
1717 _ = @import("behavior/bugs/1277.zig");
18 _ = @import("behavior/bugs/1310.zig");
1819 _ = @import("behavior/bugs/1322.zig");
1920 _ = @import("behavior/bugs/1381.zig");
2021 _ = @import("behavior/bugs/1421.zig");
......@@ -22,15 +23,18 @@ comptime {
2223 _ = @import("behavior/bugs/1486.zig");
2324 _ = @import("behavior/bugs/1500.zig");
2425 _ = @import("behavior/bugs/1607.zig");
26 _ = @import("behavior/bugs/1735.zig");
2527 _ = @import("behavior/bugs/1851.zig");
2628 _ = @import("behavior/bugs/1914.zig");
2729 _ = @import("behavior/bugs/2006.zig");
2830 _ = @import("behavior/bugs/2114.zig");
2931 _ = @import("behavior/bugs/2346.zig");
3032 _ = @import("behavior/bugs/2578.zig");
33 _ = @import("behavior/bugs/3112.zig");
3134 _ = @import("behavior/bugs/394.zig");
3235 _ = @import("behavior/bugs/421.zig");
3336 _ = @import("behavior/bugs/529.zig");
37 _ = @import("behavior/bugs/624.zig");
3438 _ = @import("behavior/bugs/655.zig");
3539 _ = @import("behavior/bugs/656.zig");
3640 _ = @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" {
290290 expect((@ptrToInt(&default_aligned_global.badguy) % 16) == 0);
291291 expect(12 == default_aligned_global.badguy);
292292}
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
292292 };
293293 S.doTheTest();
294294}
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" {
375375 S.entry();
376376 //comptime S.entry(); TODO
377377}
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
706706 var foo = E{ .entries = [_]u32{} };
707707 expect(foo.entries.len == 0);
708708}
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" {
100100 S.entry();
101101 comptime S.entry();
102102}
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 {
504504 }
505505};
506506
507comptime {
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);
507const HashToContents = std.StringHashMap(Contents);
511508const TargetToHash = std.HashMap(DestTarget, []const u8, DestTarget.hash, DestTarget.eql);
512const PathTable = std.AutoHashMap([]const u8, *TargetToHash);
509const PathTable = std.StringHashMap(*TargetToHash);
513510
514511const LibCVendor = enum {
515512 musl,
tools/update_glibc.zig+3-3
......@@ -118,7 +118,7 @@ const FunctionSet = struct {
118118 list: std.ArrayList(VersionedFn),
119119 fn_vers_list: FnVersionList,
120120};
121const FnVersionList = std.AutoHashMap([]const u8, std.ArrayList(usize));
121const FnVersionList = std.StringHashMap(std.ArrayList(usize));
122122
123123const VersionedFn = struct {
124124 ver: []const u8, // example: "GLIBC_2.15"
......@@ -140,8 +140,8 @@ pub fn main() !void {
140140 const prefix = try fs.path.join(allocator, [_][]const u8{ in_glibc_dir, "sysdeps", "unix", "sysv", "linux" });
141141 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);
144 var global_ver_set = std.AutoHashMap([]const u8, usize).init(allocator);
143 var global_fn_set = std.StringHashMap(Function).init(allocator);
144 var global_ver_set = std.StringHashMap(usize).init(allocator);
145145 var target_functions = std.AutoHashMap(usize, FunctionSet).init(allocator);
146146
147147 for (abi_lists) |*abi_list| {