authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-01-24 20:38:56-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-01-24 21:53:57-07:00
loga2abbeef90bc3fa33acaf85902b4b97383999aaf
treeba7dfaf67adf2420ac40cbb765e01407387c399b
parent8bb679bc6e25d1f7c08bb4e5e5272ae5f27aed47

stage2: rework a lot of stuff

AstGen: * rename the known_has_bits flag to known_non_opv to make it better reflect what it actually means. * add a known_comptime_only flag. * make the flags take advantage of identifiers of primitives and the fact that zig has no shadowing. * correct the known_non_opv flag for function bodies. Sema: * Rename `hasCodeGenBits` to `hasRuntimeBits` to better reflect what it does. - This function got a bit more complicated in this commit because of the duality of function bodies: on one hand they have runtime bits, but on the other hand they require being comptime known. * WipAnonDecl now takes a LazySrcDecl parameter and performs the type resolutions that it needs during finish(). * Implement comptime `@ptrToInt`. Codegen: * Improved handling of lowering decl_ref; make it work for comptime-known ptr-to-int values. - This same change had to be made many different times; perhaps we should look into merging the implementations of `genTypedValue` across x86, arm, aarch64, and riscv.

24 files changed, 1081 insertions(+), 446 deletions(-)

src/AstGen.zig+317-12
......@@ -3828,7 +3828,8 @@ fn structDeclInner(
38283828 .fields_len = 0,
38293829 .body_len = 0,
38303830 .decls_len = 0,
3831 .known_has_bits = false,
3831 .known_non_opv = false,
3832 .known_comptime_only = false,
38323833 });
38333834 return indexToRef(decl_inst);
38343835 }
......@@ -3869,7 +3870,8 @@ fn structDeclInner(
38693870 var wip_members = try WipMembers.init(gpa, &astgen.scratch, decl_count, field_count, bits_per_field, max_field_size);
38703871 defer wip_members.deinit();
38713872
3872 var known_has_bits = false;
3873 var known_non_opv = false;
3874 var known_comptime_only = false;
38733875 for (container_decl.ast.members) |member_node| {
38743876 const member = switch (try containerMember(gz, &namespace.base, &wip_members, member_node)) {
38753877 .decl => continue,
......@@ -3892,7 +3894,10 @@ fn structDeclInner(
38923894 const doc_comment_index = try astgen.docCommentAsString(member.firstToken());
38933895 wip_members.appendToField(doc_comment_index);
38943896
3895 known_has_bits = known_has_bits or nodeImpliesRuntimeBits(tree, member.ast.type_expr);
3897 known_non_opv = known_non_opv or
3898 nodeImpliesMoreThanOnePossibleValue(tree, member.ast.type_expr);
3899 known_comptime_only = known_comptime_only or
3900 nodeImpliesComptimeOnly(tree, member.ast.type_expr);
38963901
38973902 const have_align = member.ast.align_expr != 0;
38983903 const have_value = member.ast.value_expr != 0;
......@@ -3926,7 +3931,8 @@ fn structDeclInner(
39263931 .body_len = @intCast(u32, body.len),
39273932 .fields_len = field_count,
39283933 .decls_len = decl_count,
3929 .known_has_bits = known_has_bits,
3934 .known_non_opv = known_non_opv,
3935 .known_comptime_only = known_comptime_only,
39303936 });
39313937
39323938 wip_members.finishBits(bits_per_field);
......@@ -8195,7 +8201,9 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev
81958201 }
81968202}
81978203
8198fn nodeImpliesRuntimeBits(tree: *const Ast, start_node: Ast.Node.Index) bool {
8204/// Returns `true` if it is known the type expression has more than one possible value;
8205/// `false` otherwise.
8206fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.Index) bool {
81998207 const node_tags = tree.nodes.items(.tag);
82008208 const node_datas = tree.nodes.items(.data);
82018209
......@@ -8241,7 +8249,6 @@ fn nodeImpliesRuntimeBits(tree: *const Ast, start_node: Ast.Node.Index) bool {
82418249 .multiline_string_literal,
82428250 .char_literal,
82438251 .unreachable_literal,
8244 .identifier,
82458252 .error_set_decl,
82468253 .container_decl,
82478254 .container_decl_trailing,
......@@ -8355,6 +8362,11 @@ fn nodeImpliesRuntimeBits(tree: *const Ast, start_node: Ast.Node.Index) bool {
83558362 .builtin_call_comma,
83568363 .builtin_call_two,
83578364 .builtin_call_two_comma,
8365 // these are function bodies, not pointers
8366 .fn_proto_simple,
8367 .fn_proto_multi,
8368 .fn_proto_one,
8369 .fn_proto,
83588370 => return false,
83598371
83608372 // Forward the question to the LHS sub-expression.
......@@ -8366,10 +8378,6 @@ fn nodeImpliesRuntimeBits(tree: *const Ast, start_node: Ast.Node.Index) bool {
83668378 .unwrap_optional,
83678379 => node = node_datas[node].lhs,
83688380
8369 .fn_proto_simple,
8370 .fn_proto_multi,
8371 .fn_proto_one,
8372 .fn_proto,
83738381 .ptr_type_aligned,
83748382 .ptr_type_sentinel,
83758383 .ptr_type,
......@@ -8378,6 +8386,301 @@ fn nodeImpliesRuntimeBits(tree: *const Ast, start_node: Ast.Node.Index) bool {
83788386 .anyframe_type,
83798387 .array_type_sentinel,
83808388 => return true,
8389
8390 .identifier => {
8391 const main_tokens = tree.nodes.items(.main_token);
8392 const ident_bytes = tree.tokenSlice(main_tokens[node]);
8393 if (primitives.get(ident_bytes)) |primitive| switch (primitive) {
8394 .anyerror_type,
8395 .anyframe_type,
8396 .anyopaque_type,
8397 .bool_type,
8398 .c_int_type,
8399 .c_long_type,
8400 .c_longdouble_type,
8401 .c_longlong_type,
8402 .c_short_type,
8403 .c_uint_type,
8404 .c_ulong_type,
8405 .c_ulonglong_type,
8406 .c_ushort_type,
8407 .comptime_float_type,
8408 .comptime_int_type,
8409 .f128_type,
8410 .f16_type,
8411 .f32_type,
8412 .f64_type,
8413 .i16_type,
8414 .i32_type,
8415 .i64_type,
8416 .i128_type,
8417 .i8_type,
8418 .isize_type,
8419 .type_type,
8420 .u16_type,
8421 .u32_type,
8422 .u64_type,
8423 .u128_type,
8424 .u1_type,
8425 .u8_type,
8426 .usize_type,
8427 => return true,
8428
8429 .void_type,
8430 .bool_false,
8431 .bool_true,
8432 .null_value,
8433 .undef,
8434 .noreturn_type,
8435 => return false,
8436
8437 else => unreachable, // that's all the values from `primitives`.
8438 } else {
8439 return false;
8440 }
8441 },
8442 }
8443 }
8444}
8445
8446/// Returns `true` if it is known the expression is a type that cannot be used at runtime;
8447/// `false` otherwise.
8448fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool {
8449 const node_tags = tree.nodes.items(.tag);
8450 const node_datas = tree.nodes.items(.data);
8451
8452 var node = start_node;
8453 while (true) {
8454 switch (node_tags[node]) {
8455 .root,
8456 .@"usingnamespace",
8457 .test_decl,
8458 .switch_case,
8459 .switch_case_one,
8460 .container_field_init,
8461 .container_field_align,
8462 .container_field,
8463 .asm_output,
8464 .asm_input,
8465 .global_var_decl,
8466 .local_var_decl,
8467 .simple_var_decl,
8468 .aligned_var_decl,
8469 => unreachable,
8470
8471 .@"return",
8472 .@"break",
8473 .@"continue",
8474 .bit_not,
8475 .bool_not,
8476 .@"defer",
8477 .@"errdefer",
8478 .address_of,
8479 .negation,
8480 .negation_wrap,
8481 .@"resume",
8482 .array_type,
8483 .@"suspend",
8484 .@"anytype",
8485 .fn_decl,
8486 .anyframe_literal,
8487 .integer_literal,
8488 .float_literal,
8489 .enum_literal,
8490 .string_literal,
8491 .multiline_string_literal,
8492 .char_literal,
8493 .unreachable_literal,
8494 .error_set_decl,
8495 .container_decl,
8496 .container_decl_trailing,
8497 .container_decl_two,
8498 .container_decl_two_trailing,
8499 .container_decl_arg,
8500 .container_decl_arg_trailing,
8501 .tagged_union,
8502 .tagged_union_trailing,
8503 .tagged_union_two,
8504 .tagged_union_two_trailing,
8505 .tagged_union_enum_tag,
8506 .tagged_union_enum_tag_trailing,
8507 .@"asm",
8508 .asm_simple,
8509 .add,
8510 .add_wrap,
8511 .add_sat,
8512 .array_cat,
8513 .array_mult,
8514 .assign,
8515 .assign_bit_and,
8516 .assign_bit_or,
8517 .assign_shl,
8518 .assign_shl_sat,
8519 .assign_shr,
8520 .assign_bit_xor,
8521 .assign_div,
8522 .assign_sub,
8523 .assign_sub_wrap,
8524 .assign_sub_sat,
8525 .assign_mod,
8526 .assign_add,
8527 .assign_add_wrap,
8528 .assign_add_sat,
8529 .assign_mul,
8530 .assign_mul_wrap,
8531 .assign_mul_sat,
8532 .bang_equal,
8533 .bit_and,
8534 .bit_or,
8535 .shl,
8536 .shl_sat,
8537 .shr,
8538 .bit_xor,
8539 .bool_and,
8540 .bool_or,
8541 .div,
8542 .equal_equal,
8543 .error_union,
8544 .greater_or_equal,
8545 .greater_than,
8546 .less_or_equal,
8547 .less_than,
8548 .merge_error_sets,
8549 .mod,
8550 .mul,
8551 .mul_wrap,
8552 .mul_sat,
8553 .switch_range,
8554 .field_access,
8555 .sub,
8556 .sub_wrap,
8557 .sub_sat,
8558 .slice,
8559 .slice_open,
8560 .slice_sentinel,
8561 .deref,
8562 .array_access,
8563 .error_value,
8564 .while_simple,
8565 .while_cont,
8566 .for_simple,
8567 .if_simple,
8568 .@"catch",
8569 .@"orelse",
8570 .array_init_one,
8571 .array_init_one_comma,
8572 .array_init_dot_two,
8573 .array_init_dot_two_comma,
8574 .array_init_dot,
8575 .array_init_dot_comma,
8576 .array_init,
8577 .array_init_comma,
8578 .struct_init_one,
8579 .struct_init_one_comma,
8580 .struct_init_dot_two,
8581 .struct_init_dot_two_comma,
8582 .struct_init_dot,
8583 .struct_init_dot_comma,
8584 .struct_init,
8585 .struct_init_comma,
8586 .@"while",
8587 .@"if",
8588 .@"for",
8589 .@"switch",
8590 .switch_comma,
8591 .call_one,
8592 .call_one_comma,
8593 .async_call_one,
8594 .async_call_one_comma,
8595 .call,
8596 .call_comma,
8597 .async_call,
8598 .async_call_comma,
8599 .block_two,
8600 .block_two_semicolon,
8601 .block,
8602 .block_semicolon,
8603 .builtin_call,
8604 .builtin_call_comma,
8605 .builtin_call_two,
8606 .builtin_call_two_comma,
8607 .ptr_type_aligned,
8608 .ptr_type_sentinel,
8609 .ptr_type,
8610 .ptr_type_bit_range,
8611 .optional_type,
8612 .anyframe_type,
8613 .array_type_sentinel,
8614 => return false,
8615
8616 // these are function bodies, not pointers
8617 .fn_proto_simple,
8618 .fn_proto_multi,
8619 .fn_proto_one,
8620 .fn_proto,
8621 => return true,
8622
8623 // Forward the question to the LHS sub-expression.
8624 .grouped_expression,
8625 .@"try",
8626 .@"await",
8627 .@"comptime",
8628 .@"nosuspend",
8629 .unwrap_optional,
8630 => node = node_datas[node].lhs,
8631
8632 .identifier => {
8633 const main_tokens = tree.nodes.items(.main_token);
8634 const ident_bytes = tree.tokenSlice(main_tokens[node]);
8635 if (primitives.get(ident_bytes)) |primitive| switch (primitive) {
8636 .anyerror_type,
8637 .anyframe_type,
8638 .anyopaque_type,
8639 .bool_type,
8640 .c_int_type,
8641 .c_long_type,
8642 .c_longdouble_type,
8643 .c_longlong_type,
8644 .c_short_type,
8645 .c_uint_type,
8646 .c_ulong_type,
8647 .c_ulonglong_type,
8648 .c_ushort_type,
8649 .f128_type,
8650 .f16_type,
8651 .f32_type,
8652 .f64_type,
8653 .i16_type,
8654 .i32_type,
8655 .i64_type,
8656 .i128_type,
8657 .i8_type,
8658 .isize_type,
8659 .u16_type,
8660 .u32_type,
8661 .u64_type,
8662 .u128_type,
8663 .u1_type,
8664 .u8_type,
8665 .usize_type,
8666 .void_type,
8667 .bool_false,
8668 .bool_true,
8669 .null_value,
8670 .undef,
8671 .noreturn_type,
8672 => return false,
8673
8674 .comptime_float_type,
8675 .comptime_int_type,
8676 .type_type,
8677 => return true,
8678
8679 else => unreachable, // that's all the values from `primitives`.
8680 } else {
8681 return false;
8682 }
8683 },
83818684 }
83828685 }
83838686}
......@@ -10118,7 +10421,8 @@ const GenZir = struct {
1011810421 fields_len: u32,
1011910422 decls_len: u32,
1012010423 layout: std.builtin.TypeInfo.ContainerLayout,
10121 known_has_bits: bool,
10424 known_non_opv: bool,
10425 known_comptime_only: bool,
1012210426 }) !void {
1012310427 const astgen = gz.astgen;
1012410428 const gpa = astgen.gpa;
......@@ -10148,7 +10452,8 @@ const GenZir = struct {
1014810452 .has_body_len = args.body_len != 0,
1014910453 .has_fields_len = args.fields_len != 0,
1015010454 .has_decls_len = args.decls_len != 0,
10151 .known_has_bits = args.known_has_bits,
10455 .known_non_opv = args.known_non_opv,
10456 .known_comptime_only = args.known_comptime_only,
1015210457 .name_strategy = gz.anon_name_strategy,
1015310458 .layout = args.layout,
1015410459 }),
src/Compilation.zig-1
......@@ -2703,7 +2703,6 @@ fn processOneJob(comp: *Compilation, job: Job, main_progress_node: *std.Progress
27032703
27042704 const module = comp.bin_file.options.module.?;
27052705 assert(decl.has_tv);
2706 assert(decl.ty.hasCodeGenBits());
27072706
27082707 if (decl.alive) {
27092708 try module.linkerUpdateDecl(decl);
src/Module.zig+24-15
......@@ -848,9 +848,11 @@ pub const Struct = struct {
848848 // which `have_layout` does not ensure.
849849 fully_resolved,
850850 },
851 /// If true, definitely nonzero size at runtime. If false, resolving the fields
852 /// is necessary to determine whether it has bits at runtime.
853 known_has_bits: bool,
851 /// If true, has more than one possible value. However it may still be non-runtime type
852 /// if it is a comptime-only type.
853 /// If false, resolving the fields is necessary to determine whether the type has only
854 /// one possible value.
855 known_non_opv: bool,
854856 requires_comptime: RequiresComptime = .unknown,
855857
856858 pub const Fields = std.StringArrayHashMapUnmanaged(Field);
......@@ -1146,7 +1148,7 @@ pub const Union = struct {
11461148 pub fn hasAllZeroBitFieldTypes(u: Union) bool {
11471149 assert(u.haveFieldTypes());
11481150 for (u.fields.values()) |field| {
1149 if (field.ty.hasCodeGenBits()) return false;
1151 if (field.ty.hasRuntimeBits()) return false;
11501152 }
11511153 return true;
11521154 }
......@@ -1156,7 +1158,7 @@ pub const Union = struct {
11561158 var most_alignment: u32 = 0;
11571159 var most_index: usize = undefined;
11581160 for (u.fields.values()) |field, i| {
1159 if (!field.ty.hasCodeGenBits()) continue;
1161 if (!field.ty.hasRuntimeBits()) continue;
11601162
11611163 const field_align = a: {
11621164 if (field.abi_align.tag() == .abi_align_default) {
......@@ -1177,7 +1179,7 @@ pub const Union = struct {
11771179 var max_align: u32 = 0;
11781180 if (have_tag) max_align = u.tag_ty.abiAlignment(target);
11791181 for (u.fields.values()) |field| {
1180 if (!field.ty.hasCodeGenBits()) continue;
1182 if (!field.ty.hasRuntimeBits()) continue;
11811183
11821184 const field_align = a: {
11831185 if (field.abi_align.tag() == .abi_align_default) {
......@@ -1230,7 +1232,7 @@ pub const Union = struct {
12301232 var payload_size: u64 = 0;
12311233 var payload_align: u32 = 0;
12321234 for (u.fields.values()) |field, i| {
1233 if (!field.ty.hasCodeGenBits()) continue;
1235 if (!field.ty.hasRuntimeBits()) continue;
12341236
12351237 const field_align = a: {
12361238 if (field.abi_align.tag() == .abi_align_default) {
......@@ -3457,7 +3459,7 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {
34573459 .zir_index = undefined, // set below
34583460 .layout = .Auto,
34593461 .status = .none,
3460 .known_has_bits = undefined,
3462 .known_non_opv = undefined,
34613463 .namespace = .{
34623464 .parent = null,
34633465 .ty = struct_ty,
......@@ -3694,7 +3696,7 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool {
36943696 var type_changed = true;
36953697
36963698 if (decl.has_tv) {
3697 prev_type_has_bits = decl.ty.hasCodeGenBits();
3699 prev_type_has_bits = decl.ty.isFnOrHasRuntimeBits();
36983700 type_changed = !decl.ty.eql(decl_tv.ty);
36993701 if (decl.getFunction()) |prev_func| {
37003702 prev_is_inline = prev_func.state == .inline_only;
......@@ -3714,8 +3716,9 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool {
37143716 decl.analysis = .complete;
37153717 decl.generation = mod.generation;
37163718
3717 const is_inline = decl_tv.ty.fnCallingConvention() == .Inline;
3718 if (!is_inline and decl_tv.ty.hasCodeGenBits()) {
3719 const has_runtime_bits = try sema.fnHasRuntimeBits(&block_scope, src, decl.ty);
3720
3721 if (has_runtime_bits) {
37193722 // We don't fully codegen the decl until later, but we do need to reserve a global
37203723 // offset table index for it. This allows us to codegen decls out of dependency
37213724 // order, increasing how many computations can be done in parallel.
......@@ -3728,6 +3731,7 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool {
37283731 mod.comp.bin_file.freeDecl(decl);
37293732 }
37303733
3734 const is_inline = decl.ty.fnCallingConvention() == .Inline;
37313735 if (decl.is_exported) {
37323736 const export_src = src; // TODO make this point at `export` token
37333737 if (is_inline) {
......@@ -3748,6 +3752,7 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool {
37483752
37493753 decl.owns_tv = false;
37503754 var queue_linker_work = false;
3755 var is_extern = false;
37513756 switch (decl_tv.val.tag()) {
37523757 .variable => {
37533758 const variable = decl_tv.val.castTag(.variable).?.data;
......@@ -3764,6 +3769,7 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool {
37643769 if (decl == owner_decl) {
37653770 decl.owns_tv = true;
37663771 queue_linker_work = true;
3772 is_extern = true;
37673773 }
37683774 },
37693775
......@@ -3789,7 +3795,10 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool {
37893795 decl.analysis = .complete;
37903796 decl.generation = mod.generation;
37913797
3792 if (queue_linker_work and decl.ty.hasCodeGenBits()) {
3798 const has_runtime_bits = is_extern or
3799 (queue_linker_work and try sema.typeHasRuntimeBits(&block_scope, src, decl.ty));
3800
3801 if (has_runtime_bits) {
37933802 log.debug("queue linker work for {*} ({s})", .{ decl, decl.name });
37943803
37953804 try mod.comp.bin_file.allocateDeclIndexes(decl);
......@@ -4290,7 +4299,7 @@ pub fn clearDecl(
42904299 mod.deleteDeclExports(decl);
42914300
42924301 if (decl.has_tv) {
4293 if (decl.ty.hasCodeGenBits()) {
4302 if (decl.ty.isFnOrHasRuntimeBits()) {
42944303 mod.comp.bin_file.freeDecl(decl);
42954304
42964305 // TODO instead of a union, put this memory trailing Decl objects,
......@@ -4343,7 +4352,7 @@ pub fn deleteUnusedDecl(mod: *Module, decl: *Decl) void {
43434352 switch (mod.comp.bin_file.tag) {
43444353 .c => {}, // this linker backend has already migrated to the new API
43454354 else => if (decl.has_tv) {
4346 if (decl.ty.hasCodeGenBits()) {
4355 if (decl.ty.isFnOrHasRuntimeBits()) {
43474356 mod.comp.bin_file.freeDecl(decl);
43484357 }
43494358 },
......@@ -4740,7 +4749,7 @@ pub fn createAnonymousDeclFromDeclNamed(
47404749 // if the Decl is referenced by an instruction or another constant. Otherwise,
47414750 // the Decl will be garbage collected by the `codegen_decl` task instead of sent
47424751 // to the linker.
4743 if (typed_value.ty.hasCodeGenBits()) {
4752 if (typed_value.ty.isFnOrHasRuntimeBits()) {
47444753 try mod.comp.bin_file.allocateDeclIndexes(new_decl);
47454754 try mod.comp.anon_work_queue.writeItem(.{ .codegen_decl = new_decl });
47464755 }
src/Sema.zig+76-48
......@@ -437,9 +437,10 @@ pub const Block = struct {
437437 }
438438 }
439439
440 pub fn startAnonDecl(block: *Block) !WipAnonDecl {
440 pub fn startAnonDecl(block: *Block, src: LazySrcLoc) !WipAnonDecl {
441441 return WipAnonDecl{
442442 .block = block,
443 .src = src,
443444 .new_decl_arena = std.heap.ArenaAllocator.init(block.sema.gpa),
444445 .finished = false,
445446 };
......@@ -447,6 +448,7 @@ pub const Block = struct {
447448
448449 pub const WipAnonDecl = struct {
449450 block: *Block,
451 src: LazySrcLoc,
450452 new_decl_arena: std.heap.ArenaAllocator,
451453 finished: bool,
452454
......@@ -462,11 +464,15 @@ pub const Block = struct {
462464 }
463465
464466 pub fn finish(wad: *WipAnonDecl, ty: Type, val: Value) !*Decl {
465 const new_decl = try wad.block.sema.mod.createAnonymousDecl(wad.block, .{
467 const sema = wad.block.sema;
468 // Do this ahead of time because `createAnonymousDecl` depends on calling
469 // `type.hasRuntimeBits()`.
470 _ = try sema.typeHasRuntimeBits(wad.block, wad.src, ty);
471 const new_decl = try sema.mod.createAnonymousDecl(wad.block, .{
466472 .ty = ty,
467473 .val = val,
468474 });
469 errdefer wad.block.sema.mod.abortAnonDecl(new_decl);
475 errdefer sema.mod.abortAnonDecl(new_decl);
470476 try new_decl.finalizeNewArena(&wad.new_decl_arena);
471477 wad.finished = true;
472478 return new_decl;
......@@ -1505,9 +1511,6 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
15051511 const ptr = sema.resolveInst(bin_inst.rhs);
15061512 const addr_space = target_util.defaultAddressSpace(sema.mod.getTarget(), .local);
15071513
1508 // Needed for the call to `anon_decl.finish()` below which checks `ty.hasCodeGenBits()`.
1509 _ = try sema.typeHasOnePossibleValue(block, src, pointee_ty);
1510
15111514 if (Air.refToIndex(ptr)) |ptr_inst| {
15121515 if (sema.air_instructions.items(.tag)[ptr_inst] == .constant) {
15131516 const air_datas = sema.air_instructions.items(.data);
......@@ -1538,7 +1541,7 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
15381541 const iac = ptr_val.castTag(.inferred_alloc_comptime).?;
15391542 // There will be only one coerce_result_ptr because we are running at comptime.
15401543 // The alloc will turn into a Decl.
1541 var anon_decl = try block.startAnonDecl();
1544 var anon_decl = try block.startAnonDecl(src);
15421545 defer anon_decl.deinit();
15431546 iac.data.decl = try anon_decl.finish(
15441547 try pointee_ty.copy(anon_decl.arena()),
......@@ -1657,7 +1660,10 @@ pub fn analyzeStructDecl(
16571660 assert(extended.opcode == .struct_decl);
16581661 const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small);
16591662
1660 struct_obj.known_has_bits = small.known_has_bits;
1663 struct_obj.known_non_opv = small.known_non_opv;
1664 if (small.known_comptime_only) {
1665 struct_obj.requires_comptime = .yes;
1666 }
16611667
16621668 var extra_index: usize = extended.operand;
16631669 extra_index += @boolToInt(small.has_src_node);
......@@ -1705,7 +1711,7 @@ fn zirStructDecl(
17051711 .zir_index = inst,
17061712 .layout = small.layout,
17071713 .status = .none,
1708 .known_has_bits = undefined,
1714 .known_non_opv = undefined,
17091715 .namespace = .{
17101716 .parent = block.namespace,
17111717 .ty = struct_ty,
......@@ -2531,7 +2537,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
25312537 const bitcast_ty_ref = air_datas[bitcast_inst].ty_op.ty;
25322538
25332539 const new_decl = d: {
2534 var anon_decl = try block.startAnonDecl();
2540 var anon_decl = try block.startAnonDecl(src);
25352541 defer anon_decl.deinit();
25362542 const new_decl = try anon_decl.finish(
25372543 try final_elem_ty.copy(anon_decl.arena()),
......@@ -3115,7 +3121,7 @@ fn zirStoreToInferredPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compi
31153121 if (operand_val.tag() == .variable) {
31163122 return sema.failWithNeededComptime(block, src);
31173123 }
3118 var anon_decl = try block.startAnonDecl();
3124 var anon_decl = try block.startAnonDecl(src);
31193125 defer anon_decl.deinit();
31203126 iac.data.decl = try anon_decl.finish(
31213127 try operand_ty.copy(anon_decl.arena()),
......@@ -3187,8 +3193,7 @@ fn addStrLit(sema: *Sema, block: *Block, zir_bytes: []const u8) CompileError!Air
31873193 // after semantic analysis is complete, for example in the case of the initialization
31883194 // expression of a variable declaration. We need the memory to be in the new
31893195 // anonymous Decl's arena.
3190
3191 var anon_decl = try block.startAnonDecl();
3196 var anon_decl = try block.startAnonDecl(LazySrcLoc.unneeded);
31923197 defer anon_decl.deinit();
31933198
31943199 const bytes = try anon_decl.arena().dupeZ(u8, zir_bytes);
......@@ -5003,7 +5008,7 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
50035008
50045009 // TODO do we really want to create a Decl for this?
50055010 // The reason we do it right now is for memory management.
5006 var anon_decl = try block.startAnonDecl();
5011 var anon_decl = try block.startAnonDecl(src);
50075012 defer anon_decl.deinit();
50085013
50095014 var names = Module.ErrorSet.NameMap{};
......@@ -5784,15 +5789,16 @@ fn zirPtrToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
57845789 defer tracy.end();
57855790
57865791 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
5792 const ptr_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
57875793 const ptr = sema.resolveInst(inst_data.operand);
57885794 const ptr_ty = sema.typeOf(ptr);
57895795 if (!ptr_ty.isPtrAtRuntime()) {
5790 const ptr_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
57915796 return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ty});
57925797 }
5793 // TODO handle known-pointer-address
5794 const src = inst_data.src();
5795 try sema.requireRuntimeBlock(block, src);
5798 if (try sema.resolveMaybeUndefVal(block, ptr_src, ptr)) |ptr_val| {
5799 return sema.addConstant(Type.usize, ptr_val);
5800 }
5801 try sema.requireRuntimeBlock(block, ptr_src);
57965802 return block.addUnOp(.ptrtoint, ptr);
57975803}
57985804
......@@ -7409,7 +7415,7 @@ fn zirEmbedFile(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
74097415 },
74107416 };
74117417
7412 var anon_decl = try block.startAnonDecl();
7418 var anon_decl = try block.startAnonDecl(LazySrcLoc.unneeded);
74137419 defer anon_decl.deinit();
74147420
74157421 const bytes_including_null = embed_file.bytes[0 .. embed_file.bytes.len + 1];
......@@ -7673,7 +7679,7 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
76737679 const is_pointer = lhs_ty.zigTypeTag() == .Pointer;
76747680 const lhs_sub_val = if (is_pointer) (try sema.pointerDeref(block, lhs_src, lhs_val, lhs_ty)).? else lhs_val;
76757681 const rhs_sub_val = if (is_pointer) (try sema.pointerDeref(block, rhs_src, rhs_val, rhs_ty)).? else rhs_val;
7676 var anon_decl = try block.startAnonDecl();
7682 var anon_decl = try block.startAnonDecl(LazySrcLoc.unneeded);
76777683 defer anon_decl.deinit();
76787684
76797685 const buf = try anon_decl.arena().alloc(Value, final_len_including_sent);
......@@ -7757,7 +7763,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
77577763
77587764 const lhs_sub_val = if (lhs_ty.zigTypeTag() == .Pointer) (try sema.pointerDeref(block, lhs_src, lhs_val, lhs_ty)).? else lhs_val;
77597765
7760 var anon_decl = try block.startAnonDecl();
7766 var anon_decl = try block.startAnonDecl(src);
77617767 defer anon_decl.deinit();
77627768
77637769 const final_ty = if (mulinfo.sentinel) |sent|
......@@ -9371,7 +9377,7 @@ fn zirBuiltinSrc(
93719377 const func = sema.func orelse return sema.fail(block, src, "@src outside function", .{});
93729378
93739379 const func_name_val = blk: {
9374 var anon_decl = try block.startAnonDecl();
9380 var anon_decl = try block.startAnonDecl(src);
93759381 defer anon_decl.deinit();
93769382 const name = std.mem.span(func.owner_decl.name);
93779383 const bytes = try anon_decl.arena().dupe(u8, name[0 .. name.len + 1]);
......@@ -9383,7 +9389,7 @@ fn zirBuiltinSrc(
93839389 };
93849390
93859391 const file_name_val = blk: {
9386 var anon_decl = try block.startAnonDecl();
9392 var anon_decl = try block.startAnonDecl(src);
93879393 defer anon_decl.deinit();
93889394 const name = try func.owner_decl.getFileScope().fullPathZ(anon_decl.arena());
93899395 const new_decl = try anon_decl.finish(
......@@ -9633,7 +9639,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
96339639
96349640 const is_exhaustive = if (ty.isNonexhaustiveEnum()) Value.@"false" else Value.@"true";
96359641
9636 var fields_anon_decl = try block.startAnonDecl();
9642 var fields_anon_decl = try block.startAnonDecl(src);
96379643 defer fields_anon_decl.deinit();
96389644
96399645 const enum_field_ty = t: {
......@@ -9664,7 +9670,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
96649670
96659671 const name = enum_fields.keys()[i];
96669672 const name_val = v: {
9667 var anon_decl = try block.startAnonDecl();
9673 var anon_decl = try block.startAnonDecl(src);
96689674 defer anon_decl.deinit();
96699675 const bytes = try anon_decl.arena().dupeZ(u8, name);
96709676 const new_decl = try anon_decl.finish(
......@@ -9729,7 +9735,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
97299735 .Union => {
97309736 // TODO: look into memoizing this result.
97319737
9732 var fields_anon_decl = try block.startAnonDecl();
9738 var fields_anon_decl = try block.startAnonDecl(src);
97339739 defer fields_anon_decl.deinit();
97349740
97359741 const union_field_ty = t: {
......@@ -9753,7 +9759,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
97539759 const field = union_fields.values()[i];
97549760 const name = union_fields.keys()[i];
97559761 const name_val = v: {
9756 var anon_decl = try block.startAnonDecl();
9762 var anon_decl = try block.startAnonDecl(src);
97579763 defer anon_decl.deinit();
97589764 const bytes = try anon_decl.arena().dupeZ(u8, name);
97599765 const new_decl = try anon_decl.finish(
......@@ -9824,7 +9830,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
98249830 .Opaque => {
98259831 // TODO: look into memoizing this result.
98269832
9827 var fields_anon_decl = try block.startAnonDecl();
9833 var fields_anon_decl = try block.startAnonDecl(src);
98289834 defer fields_anon_decl.deinit();
98299835
98309836 const opaque_ty = try sema.resolveTypeFields(block, src, ty);
......@@ -9862,7 +9868,7 @@ fn typeInfoDecls(
98629868 const decls_len = namespace.decls.count();
98639869 if (decls_len == 0) return Value.initTag(.empty_array);
98649870
9865 var decls_anon_decl = try block.startAnonDecl();
9871 var decls_anon_decl = try block.startAnonDecl(src);
98669872 defer decls_anon_decl.deinit();
98679873
98689874 const declaration_ty = t: {
......@@ -9883,7 +9889,7 @@ fn typeInfoDecls(
98839889 const decl = namespace.decls.values()[i];
98849890 const name = namespace.decls.keys()[i];
98859891 const name_val = v: {
9886 var anon_decl = try block.startAnonDecl();
9892 var anon_decl = try block.startAnonDecl(src);
98879893 defer anon_decl.deinit();
98889894 const bytes = try anon_decl.arena().dupeZ(u8, name);
98899895 const new_decl = try anon_decl.finish(
......@@ -10668,7 +10674,7 @@ fn zirArrayInit(
1066810674 } else null;
1066910675
1067010676 const runtime_src = opt_runtime_src orelse {
10671 var anon_decl = try block.startAnonDecl();
10677 var anon_decl = try block.startAnonDecl(src);
1067210678 defer anon_decl.deinit();
1067310679
1067410680 const elem_vals = try anon_decl.arena().alloc(Value, resolved_args.len);
......@@ -10754,7 +10760,7 @@ fn zirArrayInitAnon(
1075410760 const tuple_val = try Value.Tag.@"struct".create(sema.arena, values);
1075510761 if (!is_ref) return sema.addConstant(tuple_ty, tuple_val);
1075610762
10757 var anon_decl = try block.startAnonDecl();
10763 var anon_decl = try block.startAnonDecl(src);
1075810764 defer anon_decl.deinit();
1075910765 const decl = try anon_decl.finish(
1076010766 try tuple_ty.copy(anon_decl.arena()),
......@@ -11046,7 +11052,7 @@ fn zirTypeName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1104611052 const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
1104711053 const ty = try sema.resolveType(block, ty_src, inst_data.operand);
1104811054
11049 var anon_decl = try block.startAnonDecl();
11055 var anon_decl = try block.startAnonDecl(LazySrcLoc.unneeded);
1105011056 defer anon_decl.deinit();
1105111057
1105211058 const bytes = try ty.nameAlloc(anon_decl.arena());
......@@ -12867,7 +12873,7 @@ fn safetyPanic(
1286712873 const msg_inst = msg_inst: {
1286812874 // TODO instead of making a new decl for every panic in the entire compilation,
1286912875 // introduce the concept of a reference-counted decl for these
12870 var anon_decl = try block.startAnonDecl();
12876 var anon_decl = try block.startAnonDecl(src);
1287112877 defer anon_decl.deinit();
1287212878 break :msg_inst try sema.analyzeDeclRef(try anon_decl.finish(
1287312879 try Type.Tag.array_u8.create(anon_decl.arena(), msg.len),
......@@ -13077,7 +13083,7 @@ fn fieldPtr(
1307713083 switch (inner_ty.zigTypeTag()) {
1307813084 .Array => {
1307913085 if (mem.eql(u8, field_name, "len")) {
13080 var anon_decl = try block.startAnonDecl();
13086 var anon_decl = try block.startAnonDecl(src);
1308113087 defer anon_decl.deinit();
1308213088 return sema.analyzeDeclRef(try anon_decl.finish(
1308313089 Type.initTag(.comptime_int),
......@@ -13103,7 +13109,7 @@ fn fieldPtr(
1310313109 const slice_ptr_ty = inner_ty.slicePtrFieldType(buf);
1310413110
1310513111 if (try sema.resolveDefinedValue(block, object_ptr_src, inner_ptr)) |val| {
13106 var anon_decl = try block.startAnonDecl();
13112 var anon_decl = try block.startAnonDecl(src);
1310713113 defer anon_decl.deinit();
1310813114
1310913115 return sema.analyzeDeclRef(try anon_decl.finish(
......@@ -13122,7 +13128,7 @@ fn fieldPtr(
1312213128 return block.addTyOp(.ptr_slice_ptr_ptr, result_ty, inner_ptr);
1312313129 } else if (mem.eql(u8, field_name, "len")) {
1312413130 if (try sema.resolveDefinedValue(block, object_ptr_src, inner_ptr)) |val| {
13125 var anon_decl = try block.startAnonDecl();
13131 var anon_decl = try block.startAnonDecl(src);
1312613132 defer anon_decl.deinit();
1312713133
1312813134 return sema.analyzeDeclRef(try anon_decl.finish(
......@@ -13172,7 +13178,7 @@ fn fieldPtr(
1317213178 });
1317313179 } else (try sema.mod.getErrorValue(field_name)).key;
1317413180
13175 var anon_decl = try block.startAnonDecl();
13181 var anon_decl = try block.startAnonDecl(src);
1317613182 defer anon_decl.deinit();
1317713183 return sema.analyzeDeclRef(try anon_decl.finish(
1317813184 try child_type.copy(anon_decl.arena()),
......@@ -13188,7 +13194,7 @@ fn fieldPtr(
1318813194 if (child_type.unionTagType()) |enum_ty| {
1318913195 if (enum_ty.enumFieldIndex(field_name)) |field_index| {
1319013196 const field_index_u32 = @intCast(u32, field_index);
13191 var anon_decl = try block.startAnonDecl();
13197 var anon_decl = try block.startAnonDecl(src);
1319213198 defer anon_decl.deinit();
1319313199 return sema.analyzeDeclRef(try anon_decl.finish(
1319413200 try enum_ty.copy(anon_decl.arena()),
......@@ -13208,7 +13214,7 @@ fn fieldPtr(
1320813214 return sema.failWithBadMemberAccess(block, child_type, field_name_src, field_name);
1320913215 };
1321013216 const field_index_u32 = @intCast(u32, field_index);
13211 var anon_decl = try block.startAnonDecl();
13217 var anon_decl = try block.startAnonDecl(src);
1321213218 defer anon_decl.deinit();
1321313219 return sema.analyzeDeclRef(try anon_decl.finish(
1321413220 try child_type.copy(anon_decl.arena()),
......@@ -13464,7 +13470,7 @@ fn structFieldPtr(
1346413470 var offset: u64 = 0;
1346513471 var running_bits: u16 = 0;
1346613472 for (struct_obj.fields.values()) |f, i| {
13467 if (!f.ty.hasCodeGenBits()) continue;
13473 if (!(try sema.typeHasRuntimeBits(block, field_name_src, f.ty))) continue;
1346813474
1346913475 const field_align = f.packedAlignment();
1347013476 if (field_align == 0) {
......@@ -14022,7 +14028,6 @@ fn coerce(
1402214028
1402314029 // This will give an extra hint on top of what the bottom of this func would provide.
1402414030 try sema.checkPtrOperand(block, dest_ty_src, inst_ty);
14025 unreachable;
1402614031 },
1402714032 .Int, .ComptimeInt => switch (inst_ty.zigTypeTag()) {
1402814033 .Float, .ComptimeFloat => float: {
......@@ -15340,7 +15345,7 @@ fn analyzeRef(
1534015345 const operand_ty = sema.typeOf(operand);
1534115346
1534215347 if (try sema.resolveMaybeUndefVal(block, src, operand)) |val| {
15343 var anon_decl = try block.startAnonDecl();
15348 var anon_decl = try block.startAnonDecl(src);
1534415349 defer anon_decl.deinit();
1534515350 return sema.analyzeDeclRef(try anon_decl.finish(
1534615351 try operand_ty.copy(anon_decl.arena()),
......@@ -15754,7 +15759,7 @@ fn cmpNumeric(
1575415759 lhs_bits = bigint.toConst().bitCountTwosComp();
1575515760 break :x (zcmp != .lt);
1575615761 } else x: {
15757 lhs_bits = lhs_val.intBitCountTwosComp();
15762 lhs_bits = lhs_val.intBitCountTwosComp(target);
1575815763 break :x (lhs_val.orderAgainstZero() != .lt);
1575915764 };
1576015765 lhs_bits += @boolToInt(is_unsigned and dest_int_is_signed);
......@@ -15789,7 +15794,7 @@ fn cmpNumeric(
1578915794 rhs_bits = bigint.toConst().bitCountTwosComp();
1579015795 break :x (zcmp != .lt);
1579115796 } else x: {
15792 rhs_bits = rhs_val.intBitCountTwosComp();
15797 rhs_bits = rhs_val.intBitCountTwosComp(target);
1579315798 break :x (rhs_val.orderAgainstZero() != .lt);
1579415799 };
1579515800 rhs_bits += @boolToInt(is_unsigned and dest_int_is_signed);
......@@ -16877,6 +16882,7 @@ fn getBuiltinType(
1687716882/// in `Sema` is for calling during semantic analysis, and performs field resolution
1687816883/// to get the answer. The one in `Type` is for calling during codegen and asserts
1687916884/// that the types are already resolved.
16885/// TODO assert the return value matches `ty.onePossibleValue`
1688016886pub fn typeHasOnePossibleValue(
1688116887 sema: *Sema,
1688216888 block: *Block,
......@@ -17024,7 +17030,7 @@ pub fn typeHasOnePossibleValue(
1702417030 },
1702517031 .enum_nonexhaustive => {
1702617032 const tag_ty = ty.castTag(.enum_nonexhaustive).?.data.tag_ty;
17027 if (!tag_ty.hasCodeGenBits()) {
17033 if (!(try sema.typeHasRuntimeBits(block, src, tag_ty))) {
1702817034 return Value.zero;
1702917035 } else {
1703017036 return null;
......@@ -17288,7 +17294,7 @@ fn analyzeComptimeAlloc(
1728817294 .@"align" = alignment,
1728917295 });
1729017296
17291 var anon_decl = try block.startAnonDecl();
17297 var anon_decl = try block.startAnonDecl(src);
1729217298 defer anon_decl.deinit();
1729317299
1729417300 const align_val = if (alignment == 0)
......@@ -17478,10 +17484,10 @@ fn typePtrOrOptionalPtrTy(
1747817484 }
1747917485}
1748017486
17481/// Anything that reports hasCodeGenBits() false returns false here as well.
1748217487/// `generic_poison` will return false.
1748317488/// This function returns false negatives when structs and unions are having their
1748417489/// field types resolved.
17490/// TODO assert the return value matches `ty.comptimeOnly`
1748517491fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!bool {
1748617492 return switch (ty.tag()) {
1748717493 .u1,
......@@ -17672,3 +17678,25 @@ fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) C
1767217678 },
1767317679 };
1767417680}
17681
17682pub fn typeHasRuntimeBits(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!bool {
17683 if ((try sema.typeHasOnePossibleValue(block, src, ty)) != null) return false;
17684 if (try sema.typeRequiresComptime(block, src, ty)) return false;
17685 return true;
17686}
17687
17688/// Synchronize logic with `Type.isFnOrHasRuntimeBits`.
17689pub fn fnHasRuntimeBits(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!bool {
17690 const fn_info = ty.fnInfo();
17691 if (fn_info.is_generic) return false;
17692 if (fn_info.is_var_args) return true;
17693 switch (fn_info.cc) {
17694 // If there was a comptime calling convention, it should also return false here.
17695 .Inline => return false,
17696 else => {},
17697 }
17698 if (try sema.typeRequiresComptime(block, src, fn_info.return_type)) {
17699 return false;
17700 }
17701 return true;
17702}
src/Zir.zig+3-2
......@@ -2599,10 +2599,11 @@ pub const Inst = struct {
25992599 has_body_len: bool,
26002600 has_fields_len: bool,
26012601 has_decls_len: bool,
2602 known_has_bits: bool,
2602 known_non_opv: bool,
2603 known_comptime_only: bool,
26032604 name_strategy: NameStrategy,
26042605 layout: std.builtin.TypeInfo.ContainerLayout,
2605 _: u7 = undefined,
2606 _: u6 = undefined,
26062607 };
26072608 };
26082609
src/arch/aarch64/CodeGen.zig+40-30
......@@ -713,7 +713,7 @@ fn ensureProcessDeathCapacity(self: *Self, additional_count: usize) !void {
713713fn addDbgInfoTypeReloc(self: *Self, ty: Type) !void {
714714 switch (self.debug_output) {
715715 .dwarf => |dbg_out| {
716 assert(ty.hasCodeGenBits());
716 assert(ty.hasRuntimeBits());
717717 const index = dbg_out.dbg_info.items.len;
718718 try dbg_out.dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4
719719
......@@ -1279,7 +1279,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
12791279 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
12801280 const elem_ty = self.air.typeOfIndex(inst);
12811281 const result: MCValue = result: {
1282 if (!elem_ty.hasCodeGenBits())
1282 if (!elem_ty.hasRuntimeBits())
12831283 break :result MCValue.none;
12841284
12851285 const ptr = try self.resolveInst(ty_op.operand);
......@@ -2155,7 +2155,7 @@ fn airBoolOp(self: *Self, inst: Air.Inst.Index) !void {
21552155fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void {
21562156 const block_data = self.blocks.getPtr(block).?;
21572157
2158 if (self.air.typeOf(operand).hasCodeGenBits()) {
2158 if (self.air.typeOf(operand).hasRuntimeBits()) {
21592159 const operand_mcv = try self.resolveInst(operand);
21602160 const block_mcv = block_data.mcv;
21612161 if (block_mcv == .none) {
......@@ -2608,7 +2608,7 @@ fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {
26082608 const ref_int = @enumToInt(inst);
26092609 if (ref_int < Air.Inst.Ref.typed_value_map.len) {
26102610 const tv = Air.Inst.Ref.typed_value_map[ref_int];
2611 if (!tv.ty.hasCodeGenBits()) {
2611 if (!tv.ty.hasRuntimeBits()) {
26122612 return MCValue{ .none = {} };
26132613 }
26142614 return self.genTypedValue(tv);
......@@ -2616,7 +2616,7 @@ fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {
26162616
26172617 // If the type has no codegen bits, no need to store it.
26182618 const inst_ty = self.air.typeOf(inst);
2619 if (!inst_ty.hasCodeGenBits())
2619 if (!inst_ty.hasRuntimeBits())
26202620 return MCValue{ .none = {} };
26212621
26222622 const inst_index = @intCast(Air.Inst.Index, ref_int - Air.Inst.Ref.typed_value_map.len);
......@@ -2672,11 +2672,43 @@ fn limitImmediateType(self: *Self, operand: Air.Inst.Ref, comptime T: type) !MCV
26722672 return mcv;
26732673}
26742674
2675fn lowerDeclRef(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!MCValue {
2676 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
2677 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
2678 decl.alive = true;
2679 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
2680 const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?];
2681 const got_addr = got.p_vaddr + decl.link.elf.offset_table_index * ptr_bytes;
2682 return MCValue{ .memory = got_addr };
2683 } else if (self.bin_file.cast(link.File.MachO)) |_| {
2684 // TODO I'm hacking my way through here by repurposing .memory for storing
2685 // index to the GOT target symbol index.
2686 return MCValue{ .memory = decl.link.macho.local_sym_index };
2687 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
2688 const got_addr = coff_file.offset_table_virtual_address + decl.link.coff.offset_table_index * ptr_bytes;
2689 return MCValue{ .memory = got_addr };
2690 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {
2691 try p9.seeDecl(decl);
2692 const got_addr = p9.bases.data + decl.link.plan9.got_index.? * ptr_bytes;
2693 return MCValue{ .memory = got_addr };
2694 } else {
2695 return self.fail("TODO codegen non-ELF const Decl pointer", .{});
2696 }
2697 _ = tv;
2698}
2699
26752700fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
26762701 if (typed_value.val.isUndef())
26772702 return MCValue{ .undef = {} };
26782703 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
2679 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
2704
2705 if (typed_value.val.castTag(.decl_ref)) |payload| {
2706 return self.lowerDeclRef(typed_value, payload.data);
2707 }
2708 if (typed_value.val.castTag(.decl_ref_mut)) |payload| {
2709 return self.lowerDeclRef(typed_value, payload.data.decl);
2710 }
2711
26802712 switch (typed_value.ty.zigTypeTag()) {
26812713 .Pointer => switch (typed_value.ty.ptrSize()) {
26822714 .Slice => {
......@@ -2693,28 +2725,6 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
26932725 return self.fail("TODO codegen for const slices", .{});
26942726 },
26952727 else => {
2696 if (typed_value.val.castTag(.decl_ref)) |payload| {
2697 const decl = payload.data;
2698 decl.alive = true;
2699 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
2700 const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?];
2701 const got_addr = got.p_vaddr + decl.link.elf.offset_table_index * ptr_bytes;
2702 return MCValue{ .memory = got_addr };
2703 } else if (self.bin_file.cast(link.File.MachO)) |_| {
2704 // TODO I'm hacking my way through here by repurposing .memory for storing
2705 // index to the GOT target symbol index.
2706 return MCValue{ .memory = decl.link.macho.local_sym_index };
2707 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
2708 const got_addr = coff_file.offset_table_virtual_address + decl.link.coff.offset_table_index * ptr_bytes;
2709 return MCValue{ .memory = got_addr };
2710 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {
2711 try p9.seeDecl(decl);
2712 const got_addr = p9.bases.data + decl.link.plan9.got_index.? * ptr_bytes;
2713 return MCValue{ .memory = got_addr };
2714 } else {
2715 return self.fail("TODO codegen non-ELF const Decl pointer", .{});
2716 }
2717 }
27182728 if (typed_value.val.tag() == .int_u64) {
27192729 return MCValue{ .immediate = typed_value.val.toUnsignedInt() };
27202730 }
......@@ -2794,7 +2804,7 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
27942804 const payload_type = typed_value.ty.errorUnionPayload();
27952805 const sub_val = typed_value.val.castTag(.eu_payload).?.data;
27962806
2797 if (!payload_type.hasCodeGenBits()) {
2807 if (!payload_type.hasRuntimeBits()) {
27982808 // We use the error type directly as the type.
27992809 return self.genTypedValue(.{ .ty = error_type, .val = sub_val });
28002810 }
......@@ -2888,7 +2898,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
28882898
28892899 if (ret_ty.zigTypeTag() == .NoReturn) {
28902900 result.return_value = .{ .unreach = {} };
2891 } else if (!ret_ty.hasCodeGenBits()) {
2901 } else if (!ret_ty.hasRuntimeBits()) {
28922902 result.return_value = .{ .none = {} };
28932903 } else switch (cc) {
28942904 .Naked => unreachable,
src/arch/arm/CodeGen.zig+47-35
......@@ -1074,7 +1074,7 @@ fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {
10741074 const error_union_ty = self.air.typeOf(ty_op.operand);
10751075 const payload_ty = error_union_ty.errorUnionPayload();
10761076 const mcv = try self.resolveInst(ty_op.operand);
1077 if (!payload_ty.hasCodeGenBits()) break :result mcv;
1077 if (!payload_ty.hasRuntimeBits()) break :result mcv;
10781078
10791079 return self.fail("TODO implement unwrap error union error for non-empty payloads", .{});
10801080 };
......@@ -1086,7 +1086,7 @@ fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void {
10861086 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
10871087 const error_union_ty = self.air.typeOf(ty_op.operand);
10881088 const payload_ty = error_union_ty.errorUnionPayload();
1089 if (!payload_ty.hasCodeGenBits()) break :result MCValue.none;
1089 if (!payload_ty.hasRuntimeBits()) break :result MCValue.none;
10901090
10911091 return self.fail("TODO implement unwrap error union payload for non-empty payloads", .{});
10921092 };
......@@ -1135,7 +1135,7 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
11351135 const error_union_ty = self.air.getRefType(ty_op.ty);
11361136 const payload_ty = error_union_ty.errorUnionPayload();
11371137 const mcv = try self.resolveInst(ty_op.operand);
1138 if (!payload_ty.hasCodeGenBits()) break :result mcv;
1138 if (!payload_ty.hasRuntimeBits()) break :result mcv;
11391139
11401140 return self.fail("TODO implement wrap errunion error for non-empty payloads", .{});
11411141 };
......@@ -1506,7 +1506,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
15061506 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
15071507 const elem_ty = self.air.typeOfIndex(inst);
15081508 const result: MCValue = result: {
1509 if (!elem_ty.hasCodeGenBits())
1509 if (!elem_ty.hasRuntimeBits())
15101510 break :result MCValue.none;
15111511
15121512 const ptr = try self.resolveInst(ty_op.operand);
......@@ -2666,9 +2666,9 @@ fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue {
26662666 const error_type = ty.errorUnionSet();
26672667 const payload_type = ty.errorUnionPayload();
26682668
2669 if (!error_type.hasCodeGenBits()) {
2669 if (!error_type.hasRuntimeBits()) {
26702670 return MCValue{ .immediate = 0 }; // always false
2671 } else if (!payload_type.hasCodeGenBits()) {
2671 } else if (!payload_type.hasRuntimeBits()) {
26722672 if (error_type.abiSize(self.target.*) <= 4) {
26732673 const reg_mcv: MCValue = switch (operand) {
26742674 .register => operand,
......@@ -2900,7 +2900,7 @@ fn airBoolOp(self: *Self, inst: Air.Inst.Index) !void {
29002900fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void {
29012901 const block_data = self.blocks.getPtr(block).?;
29022902
2903 if (self.air.typeOf(operand).hasCodeGenBits()) {
2903 if (self.air.typeOf(operand).hasRuntimeBits()) {
29042904 const operand_mcv = try self.resolveInst(operand);
29052905 const block_mcv = block_data.mcv;
29062906 if (block_mcv == .none) {
......@@ -3658,7 +3658,7 @@ fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {
36583658 const ref_int = @enumToInt(inst);
36593659 if (ref_int < Air.Inst.Ref.typed_value_map.len) {
36603660 const tv = Air.Inst.Ref.typed_value_map[ref_int];
3661 if (!tv.ty.hasCodeGenBits()) {
3661 if (!tv.ty.hasRuntimeBits()) {
36623662 return MCValue{ .none = {} };
36633663 }
36643664 return self.genTypedValue(tv);
......@@ -3666,7 +3666,7 @@ fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {
36663666
36673667 // If the type has no codegen bits, no need to store it.
36683668 const inst_ty = self.air.typeOf(inst);
3669 if (!inst_ty.hasCodeGenBits())
3669 if (!inst_ty.hasRuntimeBits())
36703670 return MCValue{ .none = {} };
36713671
36723672 const inst_index = @intCast(Air.Inst.Index, ref_int - Air.Inst.Ref.typed_value_map.len);
......@@ -3701,11 +3701,45 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {
37013701 }
37023702}
37033703
3704fn lowerDeclRef(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!MCValue {
3705 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
3706 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
3707
3708 decl.alive = true;
3709 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
3710 const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?];
3711 const got_addr = got.p_vaddr + decl.link.elf.offset_table_index * ptr_bytes;
3712 return MCValue{ .memory = got_addr };
3713 } else if (self.bin_file.cast(link.File.MachO)) |_| {
3714 // TODO I'm hacking my way through here by repurposing .memory for storing
3715 // index to the GOT target symbol index.
3716 return MCValue{ .memory = decl.link.macho.local_sym_index };
3717 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
3718 const got_addr = coff_file.offset_table_virtual_address + decl.link.coff.offset_table_index * ptr_bytes;
3719 return MCValue{ .memory = got_addr };
3720 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {
3721 try p9.seeDecl(decl);
3722 const got_addr = p9.bases.data + decl.link.plan9.got_index.? * ptr_bytes;
3723 return MCValue{ .memory = got_addr };
3724 } else {
3725 return self.fail("TODO codegen non-ELF const Decl pointer", .{});
3726 }
3727
3728 _ = tv;
3729}
3730
37043731fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
37053732 if (typed_value.val.isUndef())
37063733 return MCValue{ .undef = {} };
37073734 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
3708 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
3735
3736 if (typed_value.val.castTag(.decl_ref)) |payload| {
3737 return self.lowerDeclRef(typed_value, payload.data);
3738 }
3739 if (typed_value.val.castTag(.decl_ref_mut)) |payload| {
3740 return self.lowerDeclRef(typed_value, payload.data.decl);
3741 }
3742
37093743 switch (typed_value.ty.zigTypeTag()) {
37103744 .Pointer => switch (typed_value.ty.ptrSize()) {
37113745 .Slice => {
......@@ -3722,28 +3756,6 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
37223756 return self.fail("TODO codegen for const slices", .{});
37233757 },
37243758 else => {
3725 if (typed_value.val.castTag(.decl_ref)) |payload| {
3726 const decl = payload.data;
3727 decl.alive = true;
3728 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
3729 const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?];
3730 const got_addr = got.p_vaddr + decl.link.elf.offset_table_index * ptr_bytes;
3731 return MCValue{ .memory = got_addr };
3732 } else if (self.bin_file.cast(link.File.MachO)) |_| {
3733 // TODO I'm hacking my way through here by repurposing .memory for storing
3734 // index to the GOT target symbol index.
3735 return MCValue{ .memory = decl.link.macho.local_sym_index };
3736 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
3737 const got_addr = coff_file.offset_table_virtual_address + decl.link.coff.offset_table_index * ptr_bytes;
3738 return MCValue{ .memory = got_addr };
3739 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {
3740 try p9.seeDecl(decl);
3741 const got_addr = p9.bases.data + decl.link.plan9.got_index.? * ptr_bytes;
3742 return MCValue{ .memory = got_addr };
3743 } else {
3744 return self.fail("TODO codegen non-ELF const Decl pointer", .{});
3745 }
3746 }
37473759 if (typed_value.val.tag() == .int_u64) {
37483760 return MCValue{ .immediate = @intCast(u32, typed_value.val.toUnsignedInt()) };
37493761 }
......@@ -3812,7 +3824,7 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
38123824 const payload_type = typed_value.ty.errorUnionPayload();
38133825
38143826 if (typed_value.val.castTag(.eu_payload)) |pl| {
3815 if (!payload_type.hasCodeGenBits()) {
3827 if (!payload_type.hasRuntimeBits()) {
38163828 // We use the error type directly as the type.
38173829 return MCValue{ .immediate = 0 };
38183830 }
......@@ -3820,7 +3832,7 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
38203832 _ = pl;
38213833 return self.fail("TODO implement error union const of type '{}' (non-error)", .{typed_value.ty});
38223834 } else {
3823 if (!payload_type.hasCodeGenBits()) {
3835 if (!payload_type.hasRuntimeBits()) {
38243836 // We use the error type directly as the type.
38253837 return self.genTypedValue(.{ .ty = error_type, .val = typed_value.val });
38263838 }
......@@ -3918,7 +3930,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
39183930
39193931 if (ret_ty.zigTypeTag() == .NoReturn) {
39203932 result.return_value = .{ .unreach = {} };
3921 } else if (!ret_ty.hasCodeGenBits()) {
3933 } else if (!ret_ty.hasRuntimeBits()) {
39223934 result.return_value = .{ .none = {} };
39233935 } else switch (cc) {
39243936 .Naked => unreachable,
src/arch/arm/Emit.zig+1-1
......@@ -372,7 +372,7 @@ fn dbgAdvancePCAndLine(self: *Emit, line: u32, column: u32) !void {
372372fn addDbgInfoTypeReloc(self: *Emit, ty: Type) !void {
373373 switch (self.debug_output) {
374374 .dwarf => |dbg_out| {
375 assert(ty.hasCodeGenBits());
375 assert(ty.hasRuntimeBits());
376376 const index = dbg_out.dbg_info.items.len;
377377 try dbg_out.dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4
378378
src/arch/riscv64/CodeGen.zig+39-30
......@@ -691,7 +691,7 @@ fn ensureProcessDeathCapacity(self: *Self, additional_count: usize) !void {
691691fn addDbgInfoTypeReloc(self: *Self, ty: Type) !void {
692692 switch (self.debug_output) {
693693 .dwarf => |dbg_out| {
694 assert(ty.hasCodeGenBits());
694 assert(ty.hasRuntimeBits());
695695 const index = dbg_out.dbg_info.items.len;
696696 try dbg_out.dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4
697697
......@@ -1223,7 +1223,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
12231223 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
12241224 const elem_ty = self.air.typeOfIndex(inst);
12251225 const result: MCValue = result: {
1226 if (!elem_ty.hasCodeGenBits())
1226 if (!elem_ty.hasRuntimeBits())
12271227 break :result MCValue.none;
12281228
12291229 const ptr = try self.resolveInst(ty_op.operand);
......@@ -1769,7 +1769,7 @@ fn airBoolOp(self: *Self, inst: Air.Inst.Index) !void {
17691769fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void {
17701770 const block_data = self.blocks.getPtr(block).?;
17711771
1772 if (self.air.typeOf(operand).hasCodeGenBits()) {
1772 if (self.air.typeOf(operand).hasRuntimeBits()) {
17731773 const operand_mcv = try self.resolveInst(operand);
17741774 const block_mcv = block_data.mcv;
17751775 if (block_mcv == .none) {
......@@ -2107,7 +2107,7 @@ fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {
21072107 const ref_int = @enumToInt(inst);
21082108 if (ref_int < Air.Inst.Ref.typed_value_map.len) {
21092109 const tv = Air.Inst.Ref.typed_value_map[ref_int];
2110 if (!tv.ty.hasCodeGenBits()) {
2110 if (!tv.ty.hasRuntimeBits()) {
21112111 return MCValue{ .none = {} };
21122112 }
21132113 return self.genTypedValue(tv);
......@@ -2115,7 +2115,7 @@ fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {
21152115
21162116 // If the type has no codegen bits, no need to store it.
21172117 const inst_ty = self.air.typeOf(inst);
2118 if (!inst_ty.hasCodeGenBits())
2118 if (!inst_ty.hasRuntimeBits())
21192119 return MCValue{ .none = {} };
21202120
21212121 const inst_index = @intCast(Air.Inst.Index, ref_int - Air.Inst.Ref.typed_value_map.len);
......@@ -2171,11 +2171,42 @@ fn limitImmediateType(self: *Self, operand: Air.Inst.Ref, comptime T: type) !MCV
21712171 return mcv;
21722172}
21732173
2174fn lowerDeclRef(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!MCValue {
2175 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
2176 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
2177 decl.alive = true;
2178 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
2179 const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?];
2180 const got_addr = got.p_vaddr + decl.link.elf.offset_table_index * ptr_bytes;
2181 return MCValue{ .memory = got_addr };
2182 } else if (self.bin_file.cast(link.File.MachO)) |_| {
2183 // TODO I'm hacking my way through here by repurposing .memory for storing
2184 // index to the GOT target symbol index.
2185 return MCValue{ .memory = decl.link.macho.local_sym_index };
2186 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
2187 const got_addr = coff_file.offset_table_virtual_address + decl.link.coff.offset_table_index * ptr_bytes;
2188 return MCValue{ .memory = got_addr };
2189 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {
2190 try p9.seeDecl(decl);
2191 const got_addr = p9.bases.data + decl.link.plan9.got_index.? * ptr_bytes;
2192 return MCValue{ .memory = got_addr };
2193 } else {
2194 return self.fail("TODO codegen non-ELF const Decl pointer", .{});
2195 }
2196 _ = tv;
2197}
2198
21742199fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
21752200 if (typed_value.val.isUndef())
21762201 return MCValue{ .undef = {} };
2202
2203 if (typed_value.val.castTag(.decl_ref)) |payload| {
2204 return self.lowerDeclRef(typed_value, payload.data);
2205 }
2206 if (typed_value.val.castTag(.decl_ref_mut)) |payload| {
2207 return self.lowerDeclRef(typed_value, payload.data.decl);
2208 }
21772209 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
2178 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
21792210 switch (typed_value.ty.zigTypeTag()) {
21802211 .Pointer => switch (typed_value.ty.ptrSize()) {
21812212 .Slice => {
......@@ -2192,28 +2223,6 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
21922223 return self.fail("TODO codegen for const slices", .{});
21932224 },
21942225 else => {
2195 if (typed_value.val.castTag(.decl_ref)) |payload| {
2196 const decl = payload.data;
2197 decl.alive = true;
2198 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
2199 const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?];
2200 const got_addr = got.p_vaddr + decl.link.elf.offset_table_index * ptr_bytes;
2201 return MCValue{ .memory = got_addr };
2202 } else if (self.bin_file.cast(link.File.MachO)) |_| {
2203 // TODO I'm hacking my way through here by repurposing .memory for storing
2204 // index to the GOT target symbol index.
2205 return MCValue{ .memory = decl.link.macho.local_sym_index };
2206 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
2207 const got_addr = coff_file.offset_table_virtual_address + decl.link.coff.offset_table_index * ptr_bytes;
2208 return MCValue{ .memory = got_addr };
2209 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {
2210 try p9.seeDecl(decl);
2211 const got_addr = p9.bases.data + decl.link.plan9.got_index.? * ptr_bytes;
2212 return MCValue{ .memory = got_addr };
2213 } else {
2214 return self.fail("TODO codegen non-ELF const Decl pointer", .{});
2215 }
2216 }
22172226 if (typed_value.val.tag() == .int_u64) {
22182227 return MCValue{ .immediate = typed_value.val.toUnsignedInt() };
22192228 }
......@@ -2290,7 +2299,7 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
22902299 const payload_type = typed_value.ty.errorUnionPayload();
22912300 const sub_val = typed_value.val.castTag(.eu_payload).?.data;
22922301
2293 if (!payload_type.hasCodeGenBits()) {
2302 if (!payload_type.hasRuntimeBits()) {
22942303 // We use the error type directly as the type.
22952304 return self.genTypedValue(.{ .ty = error_type, .val = sub_val });
22962305 }
......@@ -2381,7 +2390,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
23812390
23822391 if (ret_ty.zigTypeTag() == .NoReturn) {
23832392 result.return_value = .{ .unreach = {} };
2384 } else if (!ret_ty.hasCodeGenBits()) {
2393 } else if (!ret_ty.hasRuntimeBits()) {
23852394 result.return_value = .{ .none = {} };
23862395 } else switch (cc) {
23872396 .Naked => unreachable,
src/arch/wasm/CodeGen.zig+35-35
......@@ -598,7 +598,7 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!WValue {
598598 // means we must generate it from a constant.
599599 const val = self.air.value(ref).?;
600600 const ty = self.air.typeOf(ref);
601 if (!ty.hasCodeGenBits() and !ty.isInt()) return WValue{ .none = {} };
601 if (!ty.hasRuntimeBits() and !ty.isInt()) return WValue{ .none = {} };
602602
603603 // When we need to pass the value by reference (such as a struct), we will
604604 // leverage `genTypedValue` to lower the constant to bytes and emit it
......@@ -790,13 +790,13 @@ fn genFunctype(gpa: Allocator, fn_ty: Type, target: std.Target) !wasm.Type {
790790 defer gpa.free(fn_params);
791791 fn_ty.fnParamTypes(fn_params);
792792 for (fn_params) |param_type| {
793 if (!param_type.hasCodeGenBits()) continue;
793 if (!param_type.hasRuntimeBits()) continue;
794794 try params.append(typeToValtype(param_type, target));
795795 }
796796 }
797797
798798 // return type
799 if (!want_sret and return_type.hasCodeGenBits()) {
799 if (!want_sret and return_type.hasRuntimeBits()) {
800800 try returns.append(typeToValtype(return_type, target));
801801 }
802802
......@@ -935,7 +935,7 @@ pub const DeclGen = struct {
935935 const abi_size = @intCast(usize, ty.abiSize(self.target()));
936936 const offset = abi_size - @intCast(usize, payload_type.abiSize(self.target()));
937937
938 if (!payload_type.hasCodeGenBits()) {
938 if (!payload_type.hasRuntimeBits()) {
939939 try writer.writeByteNTimes(@boolToInt(is_pl), abi_size);
940940 return Result{ .appended = {} };
941941 }
......@@ -1044,7 +1044,7 @@ pub const DeclGen = struct {
10441044 const field_vals = val.castTag(.@"struct").?.data;
10451045 for (field_vals) |field_val, index| {
10461046 const field_ty = ty.structFieldType(index);
1047 if (!field_ty.hasCodeGenBits()) continue;
1047 if (!field_ty.hasRuntimeBits()) continue;
10481048 switch (try self.genTypedValue(field_ty, field_val, writer)) {
10491049 .appended => {},
10501050 .externally_managed => |payload| try writer.writeAll(payload),
......@@ -1093,7 +1093,7 @@ pub const DeclGen = struct {
10931093 .appended => {},
10941094 }
10951095
1096 if (payload_ty.hasCodeGenBits()) {
1096 if (payload_ty.hasRuntimeBits()) {
10971097 const pl_val = if (val.castTag(.eu_payload)) |pl| pl.data else Value.initTag(.undef);
10981098 switch (try self.genTypedValue(payload_ty, pl_val, writer)) {
10991099 .externally_managed => |data| try writer.writeAll(data),
......@@ -1180,7 +1180,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) InnerError!CallWValu
11801180 .Naked => return result,
11811181 .Unspecified, .C => {
11821182 for (param_types) |ty, ty_index| {
1183 if (!ty.hasCodeGenBits()) {
1183 if (!ty.hasRuntimeBits()) {
11841184 result.args[ty_index] = .{ .none = {} };
11851185 continue;
11861186 }
......@@ -1243,7 +1243,7 @@ fn moveStack(self: *Self, offset: u32, local: u32) !void {
12431243///
12441244/// Asserts Type has codegenbits
12451245fn allocStack(self: *Self, ty: Type) !WValue {
1246 assert(ty.hasCodeGenBits());
1246 assert(ty.hasRuntimeBits());
12471247
12481248 // calculate needed stack space
12491249 const abi_size = std.math.cast(u32, ty.abiSize(self.target)) catch {
......@@ -1319,22 +1319,22 @@ fn isByRef(ty: Type, target: std.Target) bool {
13191319 .Struct,
13201320 .Frame,
13211321 .Union,
1322 => return ty.hasCodeGenBits(),
1322 => return ty.hasRuntimeBits(),
13231323 .Int => return if (ty.intInfo(target).bits > 64) true else false,
13241324 .ErrorUnion => {
1325 const has_tag = ty.errorUnionSet().hasCodeGenBits();
1326 const has_pl = ty.errorUnionPayload().hasCodeGenBits();
1325 const has_tag = ty.errorUnionSet().hasRuntimeBits();
1326 const has_pl = ty.errorUnionPayload().hasRuntimeBits();
13271327 if (!has_tag or !has_pl) return false;
1328 return ty.hasCodeGenBits();
1328 return ty.hasRuntimeBits();
13291329 },
13301330 .Optional => {
13311331 if (ty.isPtrLikeOptional()) return false;
13321332 var buf: Type.Payload.ElemType = undefined;
1333 return ty.optionalChild(&buf).hasCodeGenBits();
1333 return ty.optionalChild(&buf).hasRuntimeBits();
13341334 },
13351335 .Pointer => {
13361336 // Slices act like struct and will be passed by reference
1337 if (ty.isSlice()) return ty.hasCodeGenBits();
1337 if (ty.isSlice()) return ty.hasRuntimeBits();
13381338 return false;
13391339 },
13401340 }
......@@ -1563,7 +1563,7 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
15631563 const un_op = self.air.instructions.items(.data)[inst].un_op;
15641564 const operand = try self.resolveInst(un_op);
15651565 const ret_ty = self.air.typeOf(un_op).childType();
1566 if (!ret_ty.hasCodeGenBits()) return WValue.none;
1566 if (!ret_ty.hasRuntimeBits()) return WValue.none;
15671567
15681568 if (!isByRef(ret_ty, self.target)) {
15691569 const result = try self.load(operand, ret_ty, 0);
......@@ -1611,7 +1611,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
16111611 const arg_val = try self.resolveInst(arg_ref);
16121612
16131613 const arg_ty = self.air.typeOf(arg_ref);
1614 if (!arg_ty.hasCodeGenBits()) continue;
1614 if (!arg_ty.hasRuntimeBits()) continue;
16151615 try self.emitWValue(arg_val);
16161616 }
16171617
......@@ -1631,7 +1631,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
16311631 try self.addLabel(.call_indirect, fn_type_index);
16321632 }
16331633
1634 if (self.liveness.isUnused(inst) or !ret_ty.hasCodeGenBits()) {
1634 if (self.liveness.isUnused(inst) or !ret_ty.hasRuntimeBits()) {
16351635 return WValue.none;
16361636 } else if (ret_ty.isNoReturn()) {
16371637 try self.addTag(.@"unreachable");
......@@ -1653,7 +1653,7 @@ fn airAlloc(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
16531653 try self.initializeStack();
16541654 }
16551655
1656 if (!pointee_type.hasCodeGenBits()) {
1656 if (!pointee_type.hasRuntimeBits()) {
16571657 // when the pointee is zero-sized, we still want to create a pointer.
16581658 // but instead use a default pointer type as storage.
16591659 const zero_ptr = try self.allocStack(Type.usize);
......@@ -1678,7 +1678,7 @@ fn store(self: *Self, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErro
16781678 .ErrorUnion => {
16791679 const err_ty = ty.errorUnionSet();
16801680 const pl_ty = ty.errorUnionPayload();
1681 if (!pl_ty.hasCodeGenBits()) {
1681 if (!pl_ty.hasRuntimeBits()) {
16821682 const err_val = try self.load(rhs, err_ty, 0);
16831683 return self.store(lhs, err_val, err_ty, 0);
16841684 }
......@@ -1691,7 +1691,7 @@ fn store(self: *Self, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErro
16911691 }
16921692 var buf: Type.Payload.ElemType = undefined;
16931693 const pl_ty = ty.optionalChild(&buf);
1694 if (!pl_ty.hasCodeGenBits()) {
1694 if (!pl_ty.hasRuntimeBits()) {
16951695 return self.store(lhs, rhs, Type.initTag(.u8), 0);
16961696 }
16971697
......@@ -1750,7 +1750,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
17501750 const operand = try self.resolveInst(ty_op.operand);
17511751 const ty = self.air.getRefType(ty_op.ty);
17521752
1753 if (!ty.hasCodeGenBits()) return WValue{ .none = {} };
1753 if (!ty.hasRuntimeBits()) return WValue{ .none = {} };
17541754
17551755 if (isByRef(ty, self.target)) {
17561756 const new_local = try self.allocStack(ty);
......@@ -2146,7 +2146,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: std.math.CompareOperator) Inner
21462146 if (operand_ty.zigTypeTag() == .Optional and !operand_ty.isPtrLikeOptional()) {
21472147 var buf: Type.Payload.ElemType = undefined;
21482148 const payload_ty = operand_ty.optionalChild(&buf);
2149 if (payload_ty.hasCodeGenBits()) {
2149 if (payload_ty.hasRuntimeBits()) {
21502150 // When we hit this case, we must check the value of optionals
21512151 // that are not pointers. This means first checking against non-null for
21522152 // both lhs and rhs, as well as checking the payload are matching of lhs and rhs
......@@ -2190,7 +2190,7 @@ fn airBr(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
21902190 const block = self.blocks.get(br.block_inst).?;
21912191
21922192 // if operand has codegen bits we should break with a value
2193 if (self.air.typeOf(br.operand).hasCodeGenBits()) {
2193 if (self.air.typeOf(br.operand).hasRuntimeBits()) {
21942194 try self.emitWValue(try self.resolveInst(br.operand));
21952195
21962196 if (block.value != .none) {
......@@ -2282,7 +2282,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
22822282 const operand = try self.resolveInst(struct_field.struct_operand);
22832283 const field_index = struct_field.field_index;
22842284 const field_ty = struct_ty.structFieldType(field_index);
2285 if (!field_ty.hasCodeGenBits()) return WValue{ .none = {} };
2285 if (!field_ty.hasRuntimeBits()) return WValue{ .none = {} };
22862286 const offset = std.math.cast(u32, struct_ty.structFieldOffset(field_index, self.target)) catch {
22872287 return self.fail("Field type '{}' too big to fit into stack frame", .{field_ty});
22882288 };
......@@ -2452,7 +2452,7 @@ fn airIsErr(self: *Self, inst: Air.Inst.Index, opcode: wasm.Opcode) InnerError!W
24522452
24532453 // load the error tag value
24542454 try self.emitWValue(operand);
2455 if (pl_ty.hasCodeGenBits()) {
2455 if (pl_ty.hasRuntimeBits()) {
24562456 try self.addMemArg(.i32_load16_u, .{
24572457 .offset = 0,
24582458 .alignment = err_ty.errorUnionSet().abiAlignment(self.target),
......@@ -2474,7 +2474,7 @@ fn airUnwrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) InnerError!WValue
24742474 const operand = try self.resolveInst(ty_op.operand);
24752475 const err_ty = self.air.typeOf(ty_op.operand);
24762476 const payload_ty = err_ty.errorUnionPayload();
2477 if (!payload_ty.hasCodeGenBits()) return WValue{ .none = {} };
2477 if (!payload_ty.hasRuntimeBits()) return WValue{ .none = {} };
24782478 const offset = @intCast(u32, err_ty.errorUnionSet().abiSize(self.target));
24792479 if (isByRef(payload_ty, self.target)) {
24802480 return self.buildPointerOffset(operand, offset, .new);
......@@ -2489,7 +2489,7 @@ fn airUnwrapErrUnionError(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
24892489 const operand = try self.resolveInst(ty_op.operand);
24902490 const err_ty = self.air.typeOf(ty_op.operand);
24912491 const payload_ty = err_ty.errorUnionPayload();
2492 if (!payload_ty.hasCodeGenBits()) {
2492 if (!payload_ty.hasRuntimeBits()) {
24932493 return operand;
24942494 }
24952495
......@@ -2502,7 +2502,7 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
25022502 const operand = try self.resolveInst(ty_op.operand);
25032503
25042504 const op_ty = self.air.typeOf(ty_op.operand);
2505 if (!op_ty.hasCodeGenBits()) return operand;
2505 if (!op_ty.hasRuntimeBits()) return operand;
25062506 const err_ty = self.air.getRefType(ty_op.ty);
25072507 const offset = err_ty.errorUnionSet().abiSize(self.target);
25082508
......@@ -2580,7 +2580,7 @@ fn isNull(self: *Self, operand: WValue, optional_ty: Type, opcode: wasm.Opcode)
25802580 const payload_ty = optional_ty.optionalChild(&buf);
25812581 // When payload is zero-bits, we can treat operand as a value, rather than
25822582 // a pointer to the stack value
2583 if (payload_ty.hasCodeGenBits()) {
2583 if (payload_ty.hasRuntimeBits()) {
25842584 try self.addMemArg(.i32_load8_u, .{ .offset = 0, .alignment = 1 });
25852585 }
25862586 }
......@@ -2600,7 +2600,7 @@ fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
26002600 const operand = try self.resolveInst(ty_op.operand);
26012601 const opt_ty = self.air.typeOf(ty_op.operand);
26022602 const payload_ty = self.air.typeOfIndex(inst);
2603 if (!payload_ty.hasCodeGenBits()) return WValue{ .none = {} };
2603 if (!payload_ty.hasRuntimeBits()) return WValue{ .none = {} };
26042604 if (opt_ty.isPtrLikeOptional()) return operand;
26052605
26062606 const offset = opt_ty.abiSize(self.target) - payload_ty.abiSize(self.target);
......@@ -2621,7 +2621,7 @@ fn airOptionalPayloadPtr(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
26212621
26222622 var buf: Type.Payload.ElemType = undefined;
26232623 const payload_ty = opt_ty.optionalChild(&buf);
2624 if (!payload_ty.hasCodeGenBits() or opt_ty.isPtrLikeOptional()) {
2624 if (!payload_ty.hasRuntimeBits() or opt_ty.isPtrLikeOptional()) {
26252625 return operand;
26262626 }
26272627
......@@ -2635,7 +2635,7 @@ fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) InnerError!WValue
26352635 const opt_ty = self.air.typeOf(ty_op.operand).childType();
26362636 var buf: Type.Payload.ElemType = undefined;
26372637 const payload_ty = opt_ty.optionalChild(&buf);
2638 if (!payload_ty.hasCodeGenBits()) {
2638 if (!payload_ty.hasRuntimeBits()) {
26392639 return self.fail("TODO: Implement OptionalPayloadPtrSet for optional with zero-sized type {}", .{payload_ty});
26402640 }
26412641
......@@ -2659,7 +2659,7 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
26592659
26602660 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
26612661 const payload_ty = self.air.typeOf(ty_op.operand);
2662 if (!payload_ty.hasCodeGenBits()) {
2662 if (!payload_ty.hasRuntimeBits()) {
26632663 const non_null_bit = try self.allocStack(Type.initTag(.u1));
26642664 try self.addLabel(.local_get, non_null_bit.local);
26652665 try self.addImm32(1);
......@@ -2851,7 +2851,7 @@ fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
28512851 const slice_local = try self.allocStack(slice_ty);
28522852
28532853 // store the array ptr in the slice
2854 if (array_ty.hasCodeGenBits()) {
2854 if (array_ty.hasRuntimeBits()) {
28552855 try self.store(slice_local, operand, ty, 0);
28562856 }
28572857
......@@ -3105,7 +3105,7 @@ fn airPrefetch(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
31053105}
31063106
31073107fn cmpOptionals(self: *Self, lhs: WValue, rhs: WValue, operand_ty: Type, op: std.math.CompareOperator) InnerError!WValue {
3108 assert(operand_ty.hasCodeGenBits());
3108 assert(operand_ty.hasRuntimeBits());
31093109 assert(op == .eq or op == .neq);
31103110 var buf: Type.Payload.ElemType = undefined;
31113111 const payload_ty = operand_ty.optionalChild(&buf);
src/arch/x86_64/CodeGen.zig+49-37
......@@ -1202,7 +1202,7 @@ fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {
12021202 const err_union_ty = self.air.typeOf(ty_op.operand);
12031203 const payload_ty = err_union_ty.errorUnionPayload();
12041204 const mcv = try self.resolveInst(ty_op.operand);
1205 if (!payload_ty.hasCodeGenBits()) break :result mcv;
1205 if (!payload_ty.hasRuntimeBits()) break :result mcv;
12061206 return self.fail("TODO implement unwrap error union error for non-empty payloads", .{});
12071207 };
12081208 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
......@@ -1213,7 +1213,7 @@ fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void {
12131213 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
12141214 const err_union_ty = self.air.typeOf(ty_op.operand);
12151215 const payload_ty = err_union_ty.errorUnionPayload();
1216 if (!payload_ty.hasCodeGenBits()) break :result MCValue.none;
1216 if (!payload_ty.hasRuntimeBits()) break :result MCValue.none;
12171217 return self.fail("TODO implement unwrap error union payload for non-empty payloads", .{});
12181218 };
12191219 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
......@@ -1270,7 +1270,7 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
12701270 const error_union_ty = self.air.getRefType(ty_op.ty);
12711271 const payload_ty = error_union_ty.errorUnionPayload();
12721272 const mcv = try self.resolveInst(ty_op.operand);
1273 if (!payload_ty.hasCodeGenBits()) break :result mcv;
1273 if (!payload_ty.hasRuntimeBits()) break :result mcv;
12741274
12751275 return self.fail("TODO implement wrap errunion error for non-empty payloads", .{});
12761276 };
......@@ -1636,7 +1636,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
16361636 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
16371637 const elem_ty = self.air.typeOfIndex(inst);
16381638 const result: MCValue = result: {
1639 if (!elem_ty.hasCodeGenBits())
1639 if (!elem_ty.hasRuntimeBits())
16401640 break :result MCValue.none;
16411641
16421642 const ptr = try self.resolveInst(ty_op.operand);
......@@ -2739,9 +2739,9 @@ fn isNonNull(self: *Self, ty: Type, operand: MCValue) !MCValue {
27392739fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue {
27402740 const err_type = ty.errorUnionSet();
27412741 const payload_type = ty.errorUnionPayload();
2742 if (!err_type.hasCodeGenBits()) {
2742 if (!err_type.hasRuntimeBits()) {
27432743 return MCValue{ .immediate = 0 }; // always false
2744 } else if (!payload_type.hasCodeGenBits()) {
2744 } else if (!payload_type.hasRuntimeBits()) {
27452745 if (err_type.abiSize(self.target.*) <= 8) {
27462746 try self.genBinMathOpMir(.cmp, err_type, .unsigned, operand, MCValue{ .immediate = 0 });
27472747 return MCValue{ .compare_flags_unsigned = .gt };
......@@ -2962,7 +2962,7 @@ fn airBoolOp(self: *Self, inst: Air.Inst.Index) !void {
29622962fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void {
29632963 const block_data = self.blocks.getPtr(block).?;
29642964
2965 if (self.air.typeOf(operand).hasCodeGenBits()) {
2965 if (self.air.typeOf(operand).hasRuntimeBits()) {
29662966 const operand_mcv = try self.resolveInst(operand);
29672967 const block_mcv = block_data.mcv;
29682968 if (block_mcv == .none) {
......@@ -3913,7 +3913,7 @@ fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {
39133913 const ref_int = @enumToInt(inst);
39143914 if (ref_int < Air.Inst.Ref.typed_value_map.len) {
39153915 const tv = Air.Inst.Ref.typed_value_map[ref_int];
3916 if (!tv.ty.hasCodeGenBits()) {
3916 if (!tv.ty.hasRuntimeBits()) {
39173917 return MCValue{ .none = {} };
39183918 }
39193919 return self.genTypedValue(tv);
......@@ -3921,7 +3921,7 @@ fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {
39213921
39223922 // If the type has no codegen bits, no need to store it.
39233923 const inst_ty = self.air.typeOf(inst);
3924 if (!inst_ty.hasCodeGenBits())
3924 if (!inst_ty.hasRuntimeBits())
39253925 return MCValue{ .none = {} };
39263926
39273927 const inst_index = @intCast(Air.Inst.Index, ref_int - Air.Inst.Ref.typed_value_map.len);
......@@ -3977,11 +3977,45 @@ fn limitImmediateType(self: *Self, operand: Air.Inst.Ref, comptime T: type) !MCV
39773977 return mcv;
39783978}
39793979
3980fn lowerDeclRef(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!MCValue {
3981 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
3982 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
3983
3984 decl.alive = true;
3985 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
3986 const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?];
3987 const got_addr = got.p_vaddr + decl.link.elf.offset_table_index * ptr_bytes;
3988 return MCValue{ .memory = got_addr };
3989 } else if (self.bin_file.cast(link.File.MachO)) |_| {
3990 // TODO I'm hacking my way through here by repurposing .memory for storing
3991 // index to the GOT target symbol index.
3992 return MCValue{ .memory = decl.link.macho.local_sym_index };
3993 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
3994 const got_addr = coff_file.offset_table_virtual_address + decl.link.coff.offset_table_index * ptr_bytes;
3995 return MCValue{ .memory = got_addr };
3996 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {
3997 try p9.seeDecl(decl);
3998 const got_addr = p9.bases.data + decl.link.plan9.got_index.? * ptr_bytes;
3999 return MCValue{ .memory = got_addr };
4000 } else {
4001 return self.fail("TODO codegen non-ELF const Decl pointer", .{});
4002 }
4003
4004 _ = tv;
4005}
4006
39804007fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
39814008 if (typed_value.val.isUndef())
39824009 return MCValue{ .undef = {} };
39834010 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
3984 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
4011
4012 if (typed_value.val.castTag(.decl_ref)) |payload| {
4013 return self.lowerDeclRef(typed_value, payload.data);
4014 }
4015 if (typed_value.val.castTag(.decl_ref_mut)) |payload| {
4016 return self.lowerDeclRef(typed_value, payload.data.decl);
4017 }
4018
39854019 switch (typed_value.ty.zigTypeTag()) {
39864020 .Pointer => switch (typed_value.ty.ptrSize()) {
39874021 .Slice => {
......@@ -3998,28 +4032,6 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
39984032 return self.fail("TODO codegen for const slices", .{});
39994033 },
40004034 else => {
4001 if (typed_value.val.castTag(.decl_ref)) |payload| {
4002 const decl = payload.data;
4003 decl.alive = true;
4004 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
4005 const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?];
4006 const got_addr = got.p_vaddr + decl.link.elf.offset_table_index * ptr_bytes;
4007 return MCValue{ .memory = got_addr };
4008 } else if (self.bin_file.cast(link.File.MachO)) |_| {
4009 // TODO I'm hacking my way through here by repurposing .memory for storing
4010 // index to the GOT target symbol index.
4011 return MCValue{ .memory = decl.link.macho.local_sym_index };
4012 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
4013 const got_addr = coff_file.offset_table_virtual_address + decl.link.coff.offset_table_index * ptr_bytes;
4014 return MCValue{ .memory = got_addr };
4015 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {
4016 try p9.seeDecl(decl);
4017 const got_addr = p9.bases.data + decl.link.plan9.got_index.? * ptr_bytes;
4018 return MCValue{ .memory = got_addr };
4019 } else {
4020 return self.fail("TODO codegen non-ELF const Decl pointer", .{});
4021 }
4022 }
40234035 if (typed_value.val.tag() == .int_u64) {
40244036 return MCValue{ .immediate = typed_value.val.toUnsignedInt() };
40254037 }
......@@ -4091,7 +4103,7 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
40914103 const payload_type = typed_value.ty.errorUnionPayload();
40924104
40934105 if (typed_value.val.castTag(.eu_payload)) |pl| {
4094 if (!payload_type.hasCodeGenBits()) {
4106 if (!payload_type.hasRuntimeBits()) {
40954107 // We use the error type directly as the type.
40964108 return MCValue{ .immediate = 0 };
40974109 }
......@@ -4099,7 +4111,7 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
40994111 _ = pl;
41004112 return self.fail("TODO implement error union const of type '{}' (non-error)", .{typed_value.ty});
41014113 } else {
4102 if (!payload_type.hasCodeGenBits()) {
4114 if (!payload_type.hasRuntimeBits()) {
41034115 // We use the error type directly as the type.
41044116 return self.genTypedValue(.{ .ty = error_type, .val = typed_value.val });
41054117 }
......@@ -4156,7 +4168,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
41564168 var by_reg = std.AutoHashMap(usize, usize).init(self.bin_file.allocator);
41574169 defer by_reg.deinit();
41584170 for (param_types) |ty, i| {
4159 if (!ty.hasCodeGenBits()) continue;
4171 if (!ty.hasRuntimeBits()) continue;
41604172 const param_size = @intCast(u32, ty.abiSize(self.target.*));
41614173 const pass_in_reg = switch (ty.zigTypeTag()) {
41624174 .Bool => true,
......@@ -4178,7 +4190,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
41784190 // for (param_types) |ty, i| {
41794191 const i = count - 1;
41804192 const ty = param_types[i];
4181 if (!ty.hasCodeGenBits()) {
4193 if (!ty.hasRuntimeBits()) {
41824194 assert(cc != .C);
41834195 result.args[i] = .{ .none = {} };
41844196 continue;
......@@ -4207,7 +4219,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
42074219
42084220 if (ret_ty.zigTypeTag() == .NoReturn) {
42094221 result.return_value = .{ .unreach = {} };
4210 } else if (!ret_ty.hasCodeGenBits()) {
4222 } else if (!ret_ty.hasRuntimeBits()) {
42114223 result.return_value = .{ .none = {} };
42124224 } else switch (cc) {
42134225 .Naked => unreachable,
src/arch/x86_64/Emit.zig+1-1
......@@ -885,7 +885,7 @@ fn genArgDbgInfo(emit: *Emit, inst: Air.Inst.Index, mcv: MCValue) !void {
885885fn addDbgInfoTypeReloc(emit: *Emit, ty: Type) !void {
886886 switch (emit.debug_output) {
887887 .dwarf => |dbg_out| {
888 assert(ty.hasCodeGenBits());
888 assert(ty.hasRuntimeBits());
889889 const index = dbg_out.dbg_info.items.len;
890890 try dbg_out.dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4
891891
src/codegen.zig+1-1
......@@ -377,7 +377,7 @@ pub fn generateSymbol(
377377 const field_vals = typed_value.val.castTag(.@"struct").?.data;
378378 for (field_vals) |field_val, index| {
379379 const field_ty = typed_value.ty.structFieldType(index);
380 if (!field_ty.hasCodeGenBits()) continue;
380 if (!field_ty.hasRuntimeBits()) continue;
381381 switch (try generateSymbol(bin_file, src_loc, .{
382382 .ty = field_ty,
383383 .val = field_val,
src/codegen/c.zig+14-14
......@@ -507,7 +507,7 @@ pub const DeclGen = struct {
507507 const error_type = ty.errorUnionSet();
508508 const payload_type = ty.errorUnionPayload();
509509
510 if (!payload_type.hasCodeGenBits()) {
510 if (!payload_type.hasRuntimeBits()) {
511511 // We use the error type directly as the type.
512512 const err_val = if (val.errorUnionIsPayload()) Value.initTag(.zero) else val;
513513 return dg.renderValue(writer, error_type, err_val);
......@@ -581,7 +581,7 @@ pub const DeclGen = struct {
581581
582582 for (field_vals) |field_val, i| {
583583 const field_ty = ty.structFieldType(i);
584 if (!field_ty.hasCodeGenBits()) continue;
584 if (!field_ty.hasRuntimeBits()) continue;
585585
586586 if (i != 0) try writer.writeAll(",");
587587 try dg.renderValue(writer, field_ty, field_val);
......@@ -611,7 +611,7 @@ pub const DeclGen = struct {
611611 const index = union_ty.tag_ty.enumTagFieldIndex(union_obj.tag).?;
612612 const field_ty = ty.unionFields().values()[index].ty;
613613 const field_name = ty.unionFields().keys()[index];
614 if (field_ty.hasCodeGenBits()) {
614 if (field_ty.hasRuntimeBits()) {
615615 try writer.print(".{} = ", .{fmtIdent(field_name)});
616616 try dg.renderValue(writer, field_ty, union_obj.val);
617617 }
......@@ -652,7 +652,7 @@ pub const DeclGen = struct {
652652 }
653653 }
654654 const return_ty = dg.decl.ty.fnReturnType();
655 if (return_ty.hasCodeGenBits()) {
655 if (return_ty.hasRuntimeBits()) {
656656 try dg.renderType(w, return_ty);
657657 } else if (return_ty.zigTypeTag() == .NoReturn) {
658658 try w.writeAll("zig_noreturn void");
......@@ -784,7 +784,7 @@ pub const DeclGen = struct {
784784 var it = struct_obj.fields.iterator();
785785 while (it.next()) |entry| {
786786 const field_ty = entry.value_ptr.ty;
787 if (!field_ty.hasCodeGenBits()) continue;
787 if (!field_ty.hasRuntimeBits()) continue;
788788
789789 const alignment = entry.value_ptr.abi_align;
790790 const name: CValue = .{ .identifier = entry.key_ptr.* };
......@@ -837,7 +837,7 @@ pub const DeclGen = struct {
837837 var it = t.unionFields().iterator();
838838 while (it.next()) |entry| {
839839 const field_ty = entry.value_ptr.ty;
840 if (!field_ty.hasCodeGenBits()) continue;
840 if (!field_ty.hasRuntimeBits()) continue;
841841 const alignment = entry.value_ptr.abi_align;
842842 const name: CValue = .{ .identifier = entry.key_ptr.* };
843843 try buffer.append(' ');
......@@ -1582,7 +1582,7 @@ fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue {
15821582
15831583 const elem_type = inst_ty.elemType();
15841584 const mutability: Mutability = if (inst_ty.isConstPtr()) .Const else .Mut;
1585 if (!elem_type.hasCodeGenBits()) {
1585 if (!elem_type.isFnOrHasRuntimeBits()) {
15861586 const target = f.object.dg.module.getTarget();
15871587 const literal = switch (target.cpu.arch.ptrBitWidth()) {
15881588 32 => "(void *)0xaaaaaaaa",
......@@ -1683,7 +1683,7 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
16831683fn airRet(f: *Function, inst: Air.Inst.Index) !CValue {
16841684 const un_op = f.air.instructions.items(.data)[inst].un_op;
16851685 const writer = f.object.writer();
1686 if (f.air.typeOf(un_op).hasCodeGenBits()) {
1686 if (f.air.typeOf(un_op).isFnOrHasRuntimeBits()) {
16871687 const operand = try f.resolveInst(un_op);
16881688 try writer.writeAll("return ");
16891689 try f.writeCValue(writer, operand);
......@@ -1699,7 +1699,7 @@ fn airRetLoad(f: *Function, inst: Air.Inst.Index) !CValue {
16991699 const writer = f.object.writer();
17001700 const ptr_ty = f.air.typeOf(un_op);
17011701 const ret_ty = ptr_ty.childType();
1702 if (!ret_ty.hasCodeGenBits()) {
1702 if (!ret_ty.isFnOrHasRuntimeBits()) {
17031703 try writer.writeAll("return;\n");
17041704 }
17051705 const ptr = try f.resolveInst(un_op);
......@@ -2315,7 +2315,7 @@ fn airCall(f: *Function, inst: Air.Inst.Index) !CValue {
23152315
23162316 var result_local: CValue = .none;
23172317 if (unused_result) {
2318 if (ret_ty.hasCodeGenBits()) {
2318 if (ret_ty.hasRuntimeBits()) {
23192319 try writer.print("(void)", .{});
23202320 }
23212321 } else {
......@@ -2832,7 +2832,7 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
28322832 const operand_ty = f.air.typeOf(ty_op.operand);
28332833
28342834 const payload_ty = operand_ty.errorUnionPayload();
2835 if (!payload_ty.hasCodeGenBits()) {
2835 if (!payload_ty.hasRuntimeBits()) {
28362836 if (operand_ty.zigTypeTag() == .Pointer) {
28372837 const local = try f.allocLocal(inst_ty, .Const);
28382838 try writer.writeAll(" = *");
......@@ -2864,7 +2864,7 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, maybe_addrof: []cons
28642864 const operand_ty = f.air.typeOf(ty_op.operand);
28652865
28662866 const payload_ty = operand_ty.errorUnionPayload();
2867 if (!payload_ty.hasCodeGenBits()) {
2867 if (!payload_ty.hasRuntimeBits()) {
28682868 return CValue.none;
28692869 }
28702870
......@@ -2908,7 +2908,7 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
29082908 const operand = try f.resolveInst(ty_op.operand);
29092909 const err_un_ty = f.air.typeOfIndex(inst);
29102910 const payload_ty = err_un_ty.errorUnionPayload();
2911 if (!payload_ty.hasCodeGenBits()) {
2911 if (!payload_ty.hasRuntimeBits()) {
29122912 return operand;
29132913 }
29142914
......@@ -2951,7 +2951,7 @@ fn airIsErr(
29512951 const operand_ty = f.air.typeOf(un_op);
29522952 const local = try f.allocLocal(Type.initTag(.bool), .Const);
29532953 const payload_ty = operand_ty.errorUnionPayload();
2954 if (!payload_ty.hasCodeGenBits()) {
2954 if (!payload_ty.hasRuntimeBits()) {
29552955 try writer.print(" = {s}", .{deref_prefix});
29562956 try f.writeCValue(writer, operand);
29572957 try writer.print(" {s} 0;\n", .{op_str});
src/codegen/llvm.zig+85-71
......@@ -176,7 +176,7 @@ pub const Object = struct {
176176 /// the compiler, but the Type/Value memory here is backed by `type_map_arena`.
177177 /// TODO we need to remove entries from this map in response to incremental compilation
178178 /// but I think the frontend won't tell us about types that get deleted because
179 /// hasCodeGenBits() is false for types.
179 /// hasRuntimeBits() is false for types.
180180 type_map: TypeMap,
181181 /// The backing memory for `type_map`. Periodically garbage collected after flush().
182182 /// The code for doing the periodical GC is not yet implemented.
......@@ -463,7 +463,7 @@ pub const Object = struct {
463463
464464 const param_offset: c_uint = @boolToInt(ret_ptr != null);
465465 for (fn_info.param_types) |param_ty| {
466 if (!param_ty.hasCodeGenBits()) continue;
466 if (!param_ty.hasRuntimeBits()) continue;
467467
468468 const llvm_arg_i = @intCast(c_uint, args.items.len) + param_offset;
469469 try args.append(llvm_func.getParam(llvm_arg_i));
......@@ -710,7 +710,7 @@ pub const DeclGen = struct {
710710 // Set parameter attributes.
711711 var llvm_param_i: c_uint = @boolToInt(sret);
712712 for (fn_info.param_types) |param_ty| {
713 if (!param_ty.hasCodeGenBits()) continue;
713 if (!param_ty.hasRuntimeBits()) continue;
714714
715715 if (isByRef(param_ty)) {
716716 dg.addArgAttr(llvm_fn, llvm_param_i, "nonnull");
......@@ -845,7 +845,11 @@ pub const DeclGen = struct {
845845 }
846846 const llvm_addrspace = dg.llvmAddressSpace(t.ptrAddressSpace());
847847 const elem_ty = t.childType();
848 const llvm_elem_ty = if (elem_ty.hasCodeGenBits() or elem_ty.zigTypeTag() == .Array)
848 const lower_elem_ty = switch (elem_ty.zigTypeTag()) {
849 .Opaque, .Array, .Fn => true,
850 else => elem_ty.hasRuntimeBits(),
851 };
852 const llvm_elem_ty = if (lower_elem_ty)
849853 try dg.llvmType(elem_ty)
850854 else
851855 dg.context.intType(8);
......@@ -883,13 +887,13 @@ pub const DeclGen = struct {
883887 .Optional => {
884888 var buf: Type.Payload.ElemType = undefined;
885889 const child_type = t.optionalChild(&buf);
886 if (!child_type.hasCodeGenBits()) {
890 if (!child_type.hasRuntimeBits()) {
887891 return dg.context.intType(1);
888892 }
889893 const payload_llvm_ty = try dg.llvmType(child_type);
890894 if (t.isPtrLikeOptional()) {
891895 return payload_llvm_ty;
892 } else if (!child_type.hasCodeGenBits()) {
896 } else if (!child_type.hasRuntimeBits()) {
893897 return dg.context.intType(1);
894898 }
895899
......@@ -902,7 +906,7 @@ pub const DeclGen = struct {
902906 const error_type = t.errorUnionSet();
903907 const payload_type = t.errorUnionPayload();
904908 const llvm_error_type = try dg.llvmType(error_type);
905 if (!payload_type.hasCodeGenBits()) {
909 if (!payload_type.hasRuntimeBits()) {
906910 return llvm_error_type;
907911 }
908912 const llvm_payload_type = try dg.llvmType(payload_type);
......@@ -967,7 +971,7 @@ pub const DeclGen = struct {
967971 var big_align: u32 = 0;
968972 var running_bits: u16 = 0;
969973 for (struct_obj.fields.values()) |field| {
970 if (!field.ty.hasCodeGenBits()) continue;
974 if (!field.ty.hasRuntimeBits()) continue;
971975
972976 const field_align = field.packedAlignment();
973977 if (field_align == 0) {
......@@ -1034,7 +1038,7 @@ pub const DeclGen = struct {
10341038 }
10351039 } else {
10361040 for (struct_obj.fields.values()) |field| {
1037 if (!field.ty.hasCodeGenBits()) continue;
1041 if (!field.ty.hasRuntimeBits()) continue;
10381042 llvm_field_types.appendAssumeCapacity(try dg.llvmType(field.ty));
10391043 }
10401044 }
......@@ -1128,7 +1132,7 @@ pub const DeclGen = struct {
11281132 const sret = firstParamSRet(fn_info, target);
11291133 const return_type = fn_info.return_type;
11301134 const raw_llvm_ret_ty = try dg.llvmType(return_type);
1131 const llvm_ret_ty = if (!return_type.hasCodeGenBits() or sret)
1135 const llvm_ret_ty = if (!return_type.hasRuntimeBits() or sret)
11321136 dg.context.voidType()
11331137 else
11341138 raw_llvm_ret_ty;
......@@ -1141,7 +1145,7 @@ pub const DeclGen = struct {
11411145 }
11421146
11431147 for (fn_info.param_types) |param_ty| {
1144 if (!param_ty.hasCodeGenBits()) continue;
1148 if (!param_ty.hasRuntimeBits()) continue;
11451149
11461150 const raw_llvm_ty = try dg.llvmType(param_ty);
11471151 const actual_llvm_ty = if (!isByRef(param_ty)) raw_llvm_ty else raw_llvm_ty.pointerType(0);
......@@ -1181,29 +1185,35 @@ pub const DeclGen = struct {
11811185 const llvm_type = try dg.llvmType(tv.ty);
11821186 return if (tv.val.toBool()) llvm_type.constAllOnes() else llvm_type.constNull();
11831187 },
1184 .Int => {
1185 var bigint_space: Value.BigIntSpace = undefined;
1186 const bigint = tv.val.toBigInt(&bigint_space);
1187 const target = dg.module.getTarget();
1188 const int_info = tv.ty.intInfo(target);
1189 const llvm_type = dg.context.intType(int_info.bits);
1188 // TODO this duplicates code with Pointer but they should share the handling
1189 // of the tv.val.tag() and then Int should do extra constPtrToInt on top
1190 .Int => switch (tv.val.tag()) {
1191 .decl_ref_mut => return lowerDeclRefValue(dg, tv, tv.val.castTag(.decl_ref_mut).?.data.decl),
1192 .decl_ref => return lowerDeclRefValue(dg, tv, tv.val.castTag(.decl_ref).?.data),
1193 else => {
1194 var bigint_space: Value.BigIntSpace = undefined;
1195 const bigint = tv.val.toBigInt(&bigint_space);
1196 const target = dg.module.getTarget();
1197 const int_info = tv.ty.intInfo(target);
1198 const llvm_type = dg.context.intType(int_info.bits);
11901199
1191 const unsigned_val = v: {
1192 if (bigint.limbs.len == 1) {
1193 break :v llvm_type.constInt(bigint.limbs[0], .False);
1194 }
1195 if (@sizeOf(usize) == @sizeOf(u64)) {
1196 break :v llvm_type.constIntOfArbitraryPrecision(
1197 @intCast(c_uint, bigint.limbs.len),
1198 bigint.limbs.ptr,
1199 );
1200 const unsigned_val = v: {
1201 if (bigint.limbs.len == 1) {
1202 break :v llvm_type.constInt(bigint.limbs[0], .False);
1203 }
1204 if (@sizeOf(usize) == @sizeOf(u64)) {
1205 break :v llvm_type.constIntOfArbitraryPrecision(
1206 @intCast(c_uint, bigint.limbs.len),
1207 bigint.limbs.ptr,
1208 );
1209 }
1210 @panic("TODO implement bigint to llvm int for 32-bit compiler builds");
1211 };
1212 if (!bigint.positive) {
1213 return llvm.constNeg(unsigned_val);
12001214 }
1201 @panic("TODO implement bigint to llvm int for 32-bit compiler builds");
1202 };
1203 if (!bigint.positive) {
1204 return llvm.constNeg(unsigned_val);
1205 }
1206 return unsigned_val;
1215 return unsigned_val;
1216 },
12071217 },
12081218 .Enum => {
12091219 var int_buffer: Value.Payload.U64 = undefined;
......@@ -1375,7 +1385,7 @@ pub const DeclGen = struct {
13751385 const llvm_i1 = dg.context.intType(1);
13761386 const is_pl = !tv.val.isNull();
13771387 const non_null_bit = if (is_pl) llvm_i1.constAllOnes() else llvm_i1.constNull();
1378 if (!payload_ty.hasCodeGenBits()) {
1388 if (!payload_ty.hasRuntimeBits()) {
13791389 return non_null_bit;
13801390 }
13811391 if (tv.ty.isPtrLikeOptional()) {
......@@ -1388,6 +1398,7 @@ pub const DeclGen = struct {
13881398 return llvm_ty.constNull();
13891399 }
13901400 }
1401 assert(payload_ty.zigTypeTag() != .Fn);
13911402 const fields: [2]*const llvm.Value = .{
13921403 try dg.genTypedValue(.{
13931404 .ty = payload_ty,
......@@ -1425,7 +1436,7 @@ pub const DeclGen = struct {
14251436 const payload_type = tv.ty.errorUnionPayload();
14261437 const is_pl = tv.val.errorUnionIsPayload();
14271438
1428 if (!payload_type.hasCodeGenBits()) {
1439 if (!payload_type.hasRuntimeBits()) {
14291440 // We use the error type directly as the type.
14301441 const err_val = if (!is_pl) tv.val else Value.initTag(.zero);
14311442 return dg.genTypedValue(.{ .ty = error_type, .val = err_val });
......@@ -1463,7 +1474,7 @@ pub const DeclGen = struct {
14631474 var running_int: *const llvm.Value = llvm_struct_ty.structGetTypeAtIndex(0).constNull();
14641475 for (field_vals) |field_val, i| {
14651476 const field = fields[i];
1466 if (!field.ty.hasCodeGenBits()) continue;
1477 if (!field.ty.hasRuntimeBits()) continue;
14671478
14681479 const field_align = field.packedAlignment();
14691480 if (field_align == 0) {
......@@ -1545,7 +1556,7 @@ pub const DeclGen = struct {
15451556 } else {
15461557 for (field_vals) |field_val, i| {
15471558 const field_ty = tv.ty.structFieldType(i);
1548 if (!field_ty.hasCodeGenBits()) continue;
1559 if (!field_ty.hasRuntimeBits()) continue;
15491560
15501561 llvm_fields.appendAssumeCapacity(try dg.genTypedValue(.{
15511562 .ty = field_ty,
......@@ -1577,7 +1588,7 @@ pub const DeclGen = struct {
15771588 assert(union_obj.haveFieldTypes());
15781589 const field_ty = union_obj.fields.values()[field_index].ty;
15791590 const payload = p: {
1580 if (!field_ty.hasCodeGenBits()) {
1591 if (!field_ty.hasRuntimeBits()) {
15811592 const padding_len = @intCast(c_uint, layout.payload_size);
15821593 break :p dg.context.intType(8).arrayType(padding_len).getUndef();
15831594 }
......@@ -1789,13 +1800,14 @@ pub const DeclGen = struct {
17891800 return self.context.constStruct(&fields, fields.len, .False);
17901801 }
17911802
1792 if (!tv.ty.childType().hasCodeGenBits() or !decl.ty.hasCodeGenBits()) {
1803 const is_fn_body = decl.ty.zigTypeTag() == .Fn;
1804 if (!is_fn_body and !decl.ty.hasRuntimeBits()) {
17931805 return self.lowerPtrToVoid(tv.ty);
17941806 }
17951807
17961808 decl.markAlive();
17971809
1798 const llvm_val = if (decl.ty.zigTypeTag() == .Fn)
1810 const llvm_val = if (is_fn_body)
17991811 try self.resolveLlvmFunction(decl)
18001812 else
18011813 try self.resolveGlobalDecl(decl);
......@@ -2187,7 +2199,7 @@ pub const FuncGen = struct {
21872199 } else {
21882200 for (args) |arg, i| {
21892201 const param_ty = fn_info.param_types[i];
2190 if (!param_ty.hasCodeGenBits()) continue;
2202 if (!param_ty.hasRuntimeBits()) continue;
21912203
21922204 try llvm_args.append(try self.resolveInst(arg));
21932205 }
......@@ -2205,7 +2217,7 @@ pub const FuncGen = struct {
22052217 if (return_type.isNoReturn()) {
22062218 _ = self.builder.buildUnreachable();
22072219 return null;
2208 } else if (self.liveness.isUnused(inst) or !return_type.hasCodeGenBits()) {
2220 } else if (self.liveness.isUnused(inst) or !return_type.hasRuntimeBits()) {
22092221 return null;
22102222 } else if (sret) {
22112223 call.setCallSret(llvm_ret_ty);
......@@ -2229,7 +2241,7 @@ pub const FuncGen = struct {
22292241 _ = self.builder.buildRetVoid();
22302242 return null;
22312243 }
2232 if (!ret_ty.hasCodeGenBits()) {
2244 if (!ret_ty.hasRuntimeBits()) {
22332245 _ = self.builder.buildRetVoid();
22342246 return null;
22352247 }
......@@ -2242,7 +2254,7 @@ pub const FuncGen = struct {
22422254 const un_op = self.air.instructions.items(.data)[inst].un_op;
22432255 const ptr_ty = self.air.typeOf(un_op);
22442256 const ret_ty = ptr_ty.childType();
2245 if (!ret_ty.hasCodeGenBits() or isByRef(ret_ty)) {
2257 if (!ret_ty.hasRuntimeBits() or isByRef(ret_ty)) {
22462258 _ = self.builder.buildRetVoid();
22472259 return null;
22482260 }
......@@ -2278,7 +2290,7 @@ pub const FuncGen = struct {
22782290 .Int, .Bool, .Pointer, .ErrorSet => operand_ty,
22792291 .Optional => blk: {
22802292 const payload_ty = operand_ty.optionalChild(&opt_buffer);
2281 if (!payload_ty.hasCodeGenBits() or operand_ty.isPtrLikeOptional()) {
2293 if (!payload_ty.hasRuntimeBits() or operand_ty.isPtrLikeOptional()) {
22822294 break :blk operand_ty;
22832295 }
22842296 // We need to emit instructions to check for equality/inequality
......@@ -2402,7 +2414,8 @@ pub const FuncGen = struct {
24022414 self.builder.positionBuilderAtEnd(parent_bb);
24032415
24042416 // If the block does not return a value, we dont have to create a phi node.
2405 if (!inst_ty.hasCodeGenBits()) return null;
2417 const is_body = inst_ty.zigTypeTag() == .Fn;
2418 if (!is_body and !inst_ty.hasRuntimeBits()) return null;
24062419
24072420 const raw_llvm_ty = try self.dg.llvmType(inst_ty);
24082421
......@@ -2411,7 +2424,7 @@ pub const FuncGen = struct {
24112424 // a pointer to it. LLVM IR allows the call instruction to use function bodies instead
24122425 // of function pointers, however the phi makes it a runtime value and therefore
24132426 // the LLVM type has to be wrapped in a pointer.
2414 if (inst_ty.zigTypeTag() == .Fn or isByRef(inst_ty)) {
2427 if (is_body or isByRef(inst_ty)) {
24152428 break :ty raw_llvm_ty.pointerType(0);
24162429 }
24172430 break :ty raw_llvm_ty;
......@@ -2432,7 +2445,8 @@ pub const FuncGen = struct {
24322445
24332446 // If the break doesn't break a value, then we don't have to add
24342447 // the values to the lists.
2435 if (self.air.typeOf(branch.operand).hasCodeGenBits()) {
2448 const operand_ty = self.air.typeOf(branch.operand);
2449 if (operand_ty.hasRuntimeBits() or operand_ty.zigTypeTag() == .Fn) {
24362450 const val = try self.resolveInst(branch.operand);
24372451
24382452 // For the phi node, we need the basic blocks and the values of the
......@@ -2536,7 +2550,7 @@ pub const FuncGen = struct {
25362550 const llvm_usize = try self.dg.llvmType(Type.usize);
25372551 const len = llvm_usize.constInt(array_ty.arrayLen(), .False);
25382552 const slice_llvm_ty = try self.dg.llvmType(self.air.typeOfIndex(inst));
2539 if (!array_ty.hasCodeGenBits()) {
2553 if (!array_ty.hasRuntimeBits()) {
25402554 return self.builder.buildInsertValue(slice_llvm_ty.getUndef(), len, 1, "");
25412555 }
25422556 const operand = try self.resolveInst(ty_op.operand);
......@@ -2667,7 +2681,7 @@ pub const FuncGen = struct {
26672681 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
26682682 const ptr_ty = self.air.typeOf(bin_op.lhs);
26692683 const elem_ty = ptr_ty.childType();
2670 if (!elem_ty.hasCodeGenBits()) return null;
2684 if (!elem_ty.hasRuntimeBits()) return null;
26712685
26722686 const base_ptr = try self.resolveInst(bin_op.lhs);
26732687 const rhs = try self.resolveInst(bin_op.rhs);
......@@ -2714,7 +2728,7 @@ pub const FuncGen = struct {
27142728 const struct_llvm_val = try self.resolveInst(struct_field.struct_operand);
27152729 const field_index = struct_field.field_index;
27162730 const field_ty = struct_ty.structFieldType(field_index);
2717 if (!field_ty.hasCodeGenBits()) {
2731 if (!field_ty.hasRuntimeBits()) {
27182732 return null;
27192733 }
27202734 const target = self.dg.module.getTarget();
......@@ -2919,7 +2933,7 @@ pub const FuncGen = struct {
29192933
29202934 var buf: Type.Payload.ElemType = undefined;
29212935 const payload_ty = optional_ty.optionalChild(&buf);
2922 if (!payload_ty.hasCodeGenBits()) {
2936 if (!payload_ty.hasRuntimeBits()) {
29232937 if (invert) {
29242938 return self.builder.buildNot(operand, "");
29252939 } else {
......@@ -2951,7 +2965,7 @@ pub const FuncGen = struct {
29512965 const err_set_ty = try self.dg.llvmType(Type.initTag(.anyerror));
29522966 const zero = err_set_ty.constNull();
29532967
2954 if (!payload_ty.hasCodeGenBits()) {
2968 if (!payload_ty.hasRuntimeBits()) {
29552969 const loaded = if (operand_is_ptr) self.builder.buildLoad(operand, "") else operand;
29562970 return self.builder.buildICmp(op, loaded, zero, "");
29572971 }
......@@ -2974,7 +2988,7 @@ pub const FuncGen = struct {
29742988 const optional_ty = self.air.typeOf(ty_op.operand).childType();
29752989 var buf: Type.Payload.ElemType = undefined;
29762990 const payload_ty = optional_ty.optionalChild(&buf);
2977 if (!payload_ty.hasCodeGenBits()) {
2991 if (!payload_ty.hasRuntimeBits()) {
29782992 // We have a pointer to a zero-bit value and we need to return
29792993 // a pointer to a zero-bit value.
29802994 return operand;
......@@ -2998,7 +3012,7 @@ pub const FuncGen = struct {
29983012 var buf: Type.Payload.ElemType = undefined;
29993013 const payload_ty = optional_ty.optionalChild(&buf);
30003014 const non_null_bit = self.context.intType(1).constAllOnes();
3001 if (!payload_ty.hasCodeGenBits()) {
3015 if (!payload_ty.hasRuntimeBits()) {
30023016 // We have a pointer to a i1. We need to set it to 1 and then return the same pointer.
30033017 _ = self.builder.buildStore(non_null_bit, operand);
30043018 return operand;
......@@ -3033,7 +3047,7 @@ pub const FuncGen = struct {
30333047 const operand = try self.resolveInst(ty_op.operand);
30343048 const optional_ty = self.air.typeOf(ty_op.operand);
30353049 const payload_ty = self.air.typeOfIndex(inst);
3036 if (!payload_ty.hasCodeGenBits()) return null;
3050 if (!payload_ty.hasRuntimeBits()) return null;
30373051
30383052 if (optional_ty.isPtrLikeOptional()) {
30393053 // Payload value is the same as the optional value.
......@@ -3054,7 +3068,7 @@ pub const FuncGen = struct {
30543068 const operand = try self.resolveInst(ty_op.operand);
30553069 const err_union_ty = self.air.typeOf(ty_op.operand);
30563070 const payload_ty = err_union_ty.errorUnionPayload();
3057 if (!payload_ty.hasCodeGenBits()) return null;
3071 if (!payload_ty.hasRuntimeBits()) return null;
30583072 if (operand_is_ptr or isByRef(payload_ty)) {
30593073 return self.builder.buildStructGEP(operand, 1, "");
30603074 }
......@@ -3074,7 +3088,7 @@ pub const FuncGen = struct {
30743088 const operand_ty = self.air.typeOf(ty_op.operand);
30753089
30763090 const payload_ty = operand_ty.errorUnionPayload();
3077 if (!payload_ty.hasCodeGenBits()) {
3091 if (!payload_ty.hasRuntimeBits()) {
30783092 if (!operand_is_ptr) return operand;
30793093 return self.builder.buildLoad(operand, "");
30803094 }
......@@ -3093,7 +3107,7 @@ pub const FuncGen = struct {
30933107 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
30943108 const payload_ty = self.air.typeOf(ty_op.operand);
30953109 const non_null_bit = self.context.intType(1).constAllOnes();
3096 if (!payload_ty.hasCodeGenBits()) return non_null_bit;
3110 if (!payload_ty.hasRuntimeBits()) return non_null_bit;
30973111 const operand = try self.resolveInst(ty_op.operand);
30983112 const optional_ty = self.air.typeOfIndex(inst);
30993113 if (optional_ty.isPtrLikeOptional()) return operand;
......@@ -3121,7 +3135,7 @@ pub const FuncGen = struct {
31213135 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
31223136 const payload_ty = self.air.typeOf(ty_op.operand);
31233137 const operand = try self.resolveInst(ty_op.operand);
3124 if (!payload_ty.hasCodeGenBits()) {
3138 if (!payload_ty.hasRuntimeBits()) {
31253139 return operand;
31263140 }
31273141 const inst_ty = self.air.typeOfIndex(inst);
......@@ -3152,7 +3166,7 @@ pub const FuncGen = struct {
31523166 const err_un_ty = self.air.typeOfIndex(inst);
31533167 const payload_ty = err_un_ty.errorUnionPayload();
31543168 const operand = try self.resolveInst(ty_op.operand);
3155 if (!payload_ty.hasCodeGenBits()) {
3169 if (!payload_ty.hasRuntimeBits()) {
31563170 return operand;
31573171 }
31583172 const err_un_llvm_ty = try self.dg.llvmType(err_un_ty);
......@@ -3841,7 +3855,7 @@ pub const FuncGen = struct {
38413855 if (self.liveness.isUnused(inst)) return null;
38423856 const ptr_ty = self.air.typeOfIndex(inst);
38433857 const pointee_type = ptr_ty.childType();
3844 if (!pointee_type.hasCodeGenBits()) return self.dg.lowerPtrToVoid(ptr_ty);
3858 if (!pointee_type.isFnOrHasRuntimeBits()) return self.dg.lowerPtrToVoid(ptr_ty);
38453859
38463860 const pointee_llvm_ty = try self.dg.llvmType(pointee_type);
38473861 const alloca_inst = self.buildAlloca(pointee_llvm_ty);
......@@ -3855,7 +3869,7 @@ pub const FuncGen = struct {
38553869 if (self.liveness.isUnused(inst)) return null;
38563870 const ptr_ty = self.air.typeOfIndex(inst);
38573871 const ret_ty = ptr_ty.childType();
3858 if (!ret_ty.hasCodeGenBits()) return null;
3872 if (!ret_ty.isFnOrHasRuntimeBits()) return null;
38593873 if (self.ret_ptr) |ret_ptr| return ret_ptr;
38603874 const ret_llvm_ty = try self.dg.llvmType(ret_ty);
38613875 const target = self.dg.module.getTarget();
......@@ -4079,7 +4093,7 @@ pub const FuncGen = struct {
40794093 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
40804094 const ptr_ty = self.air.typeOf(bin_op.lhs);
40814095 const operand_ty = ptr_ty.childType();
4082 if (!operand_ty.hasCodeGenBits()) return null;
4096 if (!operand_ty.isFnOrHasRuntimeBits()) return null;
40834097 var ptr = try self.resolveInst(bin_op.lhs);
40844098 var element = try self.resolveInst(bin_op.rhs);
40854099 const opt_abi_ty = self.dg.getAtomicAbiType(operand_ty, false);
......@@ -4679,7 +4693,7 @@ pub const FuncGen = struct {
46794693 const union_obj = union_ty.cast(Type.Payload.Union).?.data;
46804694 const field = &union_obj.fields.values()[field_index];
46814695 const result_llvm_ty = try self.dg.llvmType(self.air.typeOfIndex(inst));
4682 if (!field.ty.hasCodeGenBits()) {
4696 if (!field.ty.hasRuntimeBits()) {
46834697 return null;
46844698 }
46854699 const target = self.dg.module.getTarget();
......@@ -4707,7 +4721,7 @@ pub const FuncGen = struct {
47074721
47084722 fn load(self: *FuncGen, ptr: *const llvm.Value, ptr_ty: Type) !?*const llvm.Value {
47094723 const info = ptr_ty.ptrInfo().data;
4710 if (!info.pointee_type.hasCodeGenBits()) return null;
4724 if (!info.pointee_type.hasRuntimeBits()) return null;
47114725
47124726 const target = self.dg.module.getTarget();
47134727 const ptr_alignment = ptr_ty.ptrAlignment(target);
......@@ -4762,7 +4776,7 @@ pub const FuncGen = struct {
47624776 ) void {
47634777 const info = ptr_ty.ptrInfo().data;
47644778 const elem_ty = info.pointee_type;
4765 if (!elem_ty.hasCodeGenBits()) {
4779 if (!elem_ty.isFnOrHasRuntimeBits()) {
47664780 return;
47674781 }
47684782 const target = self.dg.module.getTarget();
......@@ -5092,7 +5106,7 @@ fn llvmFieldIndex(
50925106 if (struct_obj.layout != .Packed) {
50935107 var llvm_field_index: c_uint = 0;
50945108 for (struct_obj.fields.values()) |field, i| {
5095 if (!field.ty.hasCodeGenBits())
5109 if (!field.ty.hasRuntimeBits())
50965110 continue;
50975111 if (field_index > i) {
50985112 llvm_field_index += 1;
......@@ -5119,7 +5133,7 @@ fn llvmFieldIndex(
51195133 var running_bits: u16 = 0;
51205134 var llvm_field_index: c_uint = 0;
51215135 for (struct_obj.fields.values()) |field, i| {
5122 if (!field.ty.hasCodeGenBits())
5136 if (!field.ty.hasRuntimeBits())
51235137 continue;
51245138
51255139 const field_align = field.packedAlignment();
......@@ -5232,9 +5246,9 @@ fn isByRef(ty: Type) bool {
52325246 .AnyFrame,
52335247 => return false,
52345248
5235 .Array, .Frame => return ty.hasCodeGenBits(),
5249 .Array, .Frame => return ty.hasRuntimeBits(),
52365250 .Struct => {
5237 if (!ty.hasCodeGenBits()) return false;
5251 if (!ty.hasRuntimeBits()) return false;
52385252 if (ty.castTag(.tuple)) |tuple| {
52395253 var count: usize = 0;
52405254 for (tuple.data.values) |field_val, i| {
......@@ -5252,7 +5266,7 @@ fn isByRef(ty: Type) bool {
52525266 }
52535267 return true;
52545268 },
5255 .Union => return ty.hasCodeGenBits(),
5269 .Union => return ty.hasRuntimeBits(),
52565270 .ErrorUnion => return isByRef(ty.errorUnionPayload()),
52575271 .Optional => {
52585272 var buf: Type.Payload.ElemType = undefined;
src/codegen/spirv.zig+3-3
......@@ -852,7 +852,7 @@ pub const DeclGen = struct {
852852 try self.beginSPIRVBlock(label_id);
853853
854854 // If this block didn't produce a value, simply return here.
855 if (!ty.hasCodeGenBits())
855 if (!ty.hasRuntimeBits())
856856 return null;
857857
858858 // Combine the result from the blocks using the Phi instruction.
......@@ -879,7 +879,7 @@ pub const DeclGen = struct {
879879 const block = self.blocks.get(br.block_inst).?;
880880 const operand_ty = self.air.typeOf(br.operand);
881881
882 if (operand_ty.hasCodeGenBits()) {
882 if (operand_ty.hasRuntimeBits()) {
883883 const operand_id = try self.resolve(br.operand);
884884 // current_block_label_id should not be undefined here, lest there is a br or br_void in the function's body.
885885 try block.incoming_blocks.append(self.spv.gpa, .{ .src_label_id = self.current_block_label_id, .break_value_id = operand_id });
......@@ -958,7 +958,7 @@ pub const DeclGen = struct {
958958 fn airRet(self: *DeclGen, inst: Air.Inst.Index) !void {
959959 const operand = self.air.instructions.items(.data)[inst].un_op;
960960 const operand_ty = self.air.typeOf(operand);
961 if (operand_ty.hasCodeGenBits()) {
961 if (operand_ty.hasRuntimeBits()) {
962962 const operand_id = try self.resolve(operand);
963963 try writeInstruction(&self.code, .OpReturnValue, &[_]Word{operand_id});
964964 } else {
src/link/Elf.zig+1-1
......@@ -2476,7 +2476,7 @@ pub fn updateFunc(self: *Elf, module: *Module, func: *Module.Fn, air: Air, liven
24762476 try dbg_info_buffer.ensureUnusedCapacity(25 + decl_name_with_null.len);
24772477
24782478 const fn_ret_type = decl.ty.fnReturnType();
2479 const fn_ret_has_bits = fn_ret_type.hasCodeGenBits();
2479 const fn_ret_has_bits = fn_ret_type.hasRuntimeBits();
24802480 if (fn_ret_has_bits) {
24812481 dbg_info_buffer.appendAssumeCapacity(abbrev_subprogram);
24822482 } else {
src/link/MachO/DebugSymbols.zig+1-1
......@@ -920,7 +920,7 @@ pub fn initDeclDebugBuffers(
920920 try dbg_info_buffer.ensureUnusedCapacity(27 + decl_name_with_null.len);
921921
922922 const fn_ret_type = decl.ty.fnReturnType();
923 const fn_ret_has_bits = fn_ret_type.hasCodeGenBits();
923 const fn_ret_has_bits = fn_ret_type.hasRuntimeBits();
924924 if (fn_ret_has_bits) {
925925 dbg_info_buffer.appendAssumeCapacity(abbrev_subprogram);
926926 } else {
src/link/Wasm.zig+1-1
......@@ -259,7 +259,7 @@ pub fn updateDecl(self: *Wasm, module: *Module, decl: *Module.Decl) !void {
259259 if (build_options.have_llvm) {
260260 if (self.llvm_object) |llvm_object| return llvm_object.updateDecl(module, decl);
261261 }
262 if (!decl.ty.hasCodeGenBits()) return;
262 if (!decl.ty.hasRuntimeBits()) return;
263263 assert(decl.link.wasm.sym_index != 0); // Must call allocateDeclIndexes()
264264
265265 decl.link.wasm.clear();
src/print_zir.zig+2-1
......@@ -1157,7 +1157,8 @@ const Writer = struct {
11571157 break :blk decls_len;
11581158 } else 0;
11591159
1160 try self.writeFlag(stream, "known_has_bits, ", small.known_has_bits);
1160 try self.writeFlag(stream, "known_non_opv, ", small.known_non_opv);
1161 try self.writeFlag(stream, "known_comptime_only, ", small.known_comptime_only);
11611162 try stream.print("{s}, {s}, ", .{
11621163 @tagName(small.name_strategy), @tagName(small.layout),
11631164 });
src/type.zig+273-99
......@@ -1512,8 +1512,12 @@ pub const Type = extern union {
15121512 }
15131513 }
15141514
1515 pub fn hasCodeGenBits(self: Type) bool {
1516 return switch (self.tag()) {
1515 /// true if and only if the type takes up space in memory at runtime.
1516 /// There are two reasons a type will return false:
1517 /// * the type is a comptime-only type. For example, the type `type` itself.
1518 /// * the type has only one possible value, making its ABI size 0.
1519 pub fn hasRuntimeBits(ty: Type) bool {
1520 return switch (ty.tag()) {
15171521 .u1,
15181522 .u8,
15191523 .i8,
......@@ -1542,13 +1546,9 @@ pub const Type = extern union {
15421546 .f128,
15431547 .bool,
15441548 .anyerror,
1545 .single_const_pointer_to_comptime_int,
15461549 .const_slice_u8,
15471550 .const_slice_u8_sentinel_0,
15481551 .array_u8_sentinel_0,
1549 .optional,
1550 .optional_single_mut_pointer,
1551 .optional_single_const_pointer,
15521552 .anyerror_void_error_union,
15531553 .error_set,
15541554 .error_set_single,
......@@ -1568,9 +1568,40 @@ pub const Type = extern union {
15681568 .export_options,
15691569 .extern_options,
15701570 .@"anyframe",
1571 .anyframe_T,
15721571 .anyopaque,
15731572 .@"opaque",
1573 => true,
1574
1575 // These are false because they are comptime-only types.
1576 .single_const_pointer_to_comptime_int,
1577 .void,
1578 .type,
1579 .comptime_int,
1580 .comptime_float,
1581 .noreturn,
1582 .@"null",
1583 .@"undefined",
1584 .enum_literal,
1585 .empty_struct,
1586 .empty_struct_literal,
1587 .type_info,
1588 .bound_fn,
1589 // These are function *bodies*, not pointers.
1590 // Special exceptions have to be made when emitting functions due to
1591 // this returning false.
1592 .function,
1593 .fn_noreturn_no_args,
1594 .fn_void_no_args,
1595 .fn_naked_noreturn_no_args,
1596 .fn_ccc_void_no_args,
1597 => false,
1598
1599 // These types have more than one possible value, so the result is the same as
1600 // asking whether they are comptime-only types.
1601 .anyframe_T,
1602 .optional,
1603 .optional_single_mut_pointer,
1604 .optional_single_const_pointer,
15741605 .single_const_pointer,
15751606 .single_mut_pointer,
15761607 .many_const_pointer,
......@@ -1580,102 +1611,84 @@ pub const Type = extern union {
15801611 .const_slice,
15811612 .mut_slice,
15821613 .pointer,
1583 => true,
1584
1585 .function => !self.castTag(.function).?.data.is_generic,
1586
1587 .fn_noreturn_no_args,
1588 .fn_void_no_args,
1589 .fn_naked_noreturn_no_args,
1590 .fn_ccc_void_no_args,
1591 => true,
1614 => !ty.comptimeOnly(),
15921615
15931616 .@"struct" => {
1594 const struct_obj = self.castTag(.@"struct").?.data;
1595 if (struct_obj.known_has_bits) {
1596 return true;
1617 const struct_obj = ty.castTag(.@"struct").?.data;
1618 switch (struct_obj.requires_comptime) {
1619 .wip => unreachable,
1620 .yes => return false,
1621 .no => if (struct_obj.known_non_opv) return true,
1622 .unknown => {},
15971623 }
15981624 assert(struct_obj.haveFieldTypes());
15991625 for (struct_obj.fields.values()) |value| {
1600 if (value.ty.hasCodeGenBits())
1626 if (value.ty.hasRuntimeBits())
16011627 return true;
16021628 } else {
16031629 return false;
16041630 }
16051631 },
1632
16061633 .enum_full => {
1607 const enum_full = self.castTag(.enum_full).?.data;
1634 const enum_full = ty.castTag(.enum_full).?.data;
16081635 return enum_full.fields.count() >= 2;
16091636 },
16101637 .enum_simple => {
1611 const enum_simple = self.castTag(.enum_simple).?.data;
1638 const enum_simple = ty.castTag(.enum_simple).?.data;
16121639 return enum_simple.fields.count() >= 2;
16131640 },
16141641 .enum_numbered, .enum_nonexhaustive => {
16151642 var buffer: Payload.Bits = undefined;
1616 const int_tag_ty = self.intTagType(&buffer);
1617 return int_tag_ty.hasCodeGenBits();
1643 const int_tag_ty = ty.intTagType(&buffer);
1644 return int_tag_ty.hasRuntimeBits();
16181645 },
1646
16191647 .@"union" => {
1620 const union_obj = self.castTag(.@"union").?.data;
1648 const union_obj = ty.castTag(.@"union").?.data;
16211649 assert(union_obj.haveFieldTypes());
16221650 for (union_obj.fields.values()) |value| {
1623 if (value.ty.hasCodeGenBits())
1651 if (value.ty.hasRuntimeBits())
16241652 return true;
16251653 } else {
16261654 return false;
16271655 }
16281656 },
16291657 .union_tagged => {
1630 const union_obj = self.castTag(.union_tagged).?.data;
1631 if (union_obj.tag_ty.hasCodeGenBits()) {
1658 const union_obj = ty.castTag(.union_tagged).?.data;
1659 if (union_obj.tag_ty.hasRuntimeBits()) {
16321660 return true;
16331661 }
16341662 assert(union_obj.haveFieldTypes());
16351663 for (union_obj.fields.values()) |value| {
1636 if (value.ty.hasCodeGenBits())
1664 if (value.ty.hasRuntimeBits())
16371665 return true;
16381666 } else {
16391667 return false;
16401668 }
16411669 },
16421670
1643 .array, .vector => self.elemType().hasCodeGenBits() and self.arrayLen() != 0,
1644 .array_u8 => self.arrayLen() != 0,
1671 .array, .vector => ty.arrayLen() != 0 and ty.elemType().hasRuntimeBits(),
1672 .array_u8 => ty.arrayLen() != 0,
1673 .array_sentinel => ty.childType().hasRuntimeBits(),
16451674
1646 .array_sentinel => self.childType().hasCodeGenBits(),
1647
1648 .int_signed, .int_unsigned => self.cast(Payload.Bits).?.data != 0,
1675 .int_signed, .int_unsigned => ty.cast(Payload.Bits).?.data != 0,
16491676
16501677 .error_union => {
1651 const payload = self.castTag(.error_union).?.data;
1652 return payload.error_set.hasCodeGenBits() or payload.payload.hasCodeGenBits();
1678 const payload = ty.castTag(.error_union).?.data;
1679 return payload.error_set.hasRuntimeBits() or payload.payload.hasRuntimeBits();
16531680 },
16541681
16551682 .tuple => {
1656 const tuple = self.castTag(.tuple).?.data;
1657 for (tuple.types) |ty, i| {
1683 const tuple = ty.castTag(.tuple).?.data;
1684 for (tuple.types) |field_ty, i| {
16581685 const val = tuple.values[i];
16591686 if (val.tag() != .unreachable_value) continue; // comptime field
1660 if (ty.hasCodeGenBits()) return true;
1687 if (field_ty.hasRuntimeBits()) return true;
16611688 }
16621689 return false;
16631690 },
16641691
1665 .void,
1666 .type,
1667 .comptime_int,
1668 .comptime_float,
1669 .noreturn,
1670 .@"null",
1671 .@"undefined",
1672 .enum_literal,
1673 .empty_struct,
1674 .empty_struct_literal,
1675 .type_info,
1676 .bound_fn,
1677 => false,
1678
16791692 .inferred_alloc_const => unreachable,
16801693 .inferred_alloc_mut => unreachable,
16811694 .var_args_param => unreachable,
......@@ -1683,6 +1696,24 @@ pub const Type = extern union {
16831696 };
16841697 }
16851698
1699 pub fn isFnOrHasRuntimeBits(ty: Type) bool {
1700 switch (ty.zigTypeTag()) {
1701 .Fn => {
1702 const fn_info = ty.fnInfo();
1703 if (fn_info.is_generic) return false;
1704 if (fn_info.is_var_args) return true;
1705 switch (fn_info.cc) {
1706 // If there was a comptime calling convention, it should also return false here.
1707 .Inline => return false,
1708 else => {},
1709 }
1710 if (fn_info.return_type.comptimeOnly()) return false;
1711 return true;
1712 },
1713 else => return ty.hasRuntimeBits(),
1714 }
1715 }
1716
16861717 pub fn isNoReturn(self: Type) bool {
16871718 const definitely_correct_result =
16881719 self.tag_if_small_enough != .bound_fn and
......@@ -1857,7 +1888,7 @@ pub const Type = extern union {
18571888 .optional => {
18581889 var buf: Payload.ElemType = undefined;
18591890 const child_type = self.optionalChild(&buf);
1860 if (!child_type.hasCodeGenBits()) return 1;
1891 if (!child_type.hasRuntimeBits()) return 1;
18611892
18621893 if (child_type.zigTypeTag() == .Pointer and !child_type.isCPtr())
18631894 return @divExact(target.cpu.arch.ptrBitWidth(), 8);
......@@ -1867,9 +1898,9 @@ pub const Type = extern union {
18671898
18681899 .error_union => {
18691900 const data = self.castTag(.error_union).?.data;
1870 if (!data.error_set.hasCodeGenBits()) {
1901 if (!data.error_set.hasRuntimeBits()) {
18711902 return data.payload.abiAlignment(target);
1872 } else if (!data.payload.hasCodeGenBits()) {
1903 } else if (!data.payload.hasRuntimeBits()) {
18731904 return data.error_set.abiAlignment(target);
18741905 }
18751906 return @maximum(
......@@ -1889,7 +1920,7 @@ pub const Type = extern union {
18891920 if (!is_packed) {
18901921 var big_align: u32 = 0;
18911922 for (fields.values()) |field| {
1892 if (!field.ty.hasCodeGenBits()) continue;
1923 if (!field.ty.hasRuntimeBits()) continue;
18931924
18941925 const field_align = field.normalAlignment(target);
18951926 big_align = @maximum(big_align, field_align);
......@@ -1903,7 +1934,7 @@ pub const Type = extern union {
19031934 var running_bits: u16 = 0;
19041935
19051936 for (fields.values()) |field| {
1906 if (!field.ty.hasCodeGenBits()) continue;
1937 if (!field.ty.hasRuntimeBits()) continue;
19071938
19081939 const field_align = field.packedAlignment();
19091940 if (field_align == 0) {
......@@ -1941,7 +1972,7 @@ pub const Type = extern union {
19411972 for (tuple.types) |field_ty, i| {
19421973 const val = tuple.values[i];
19431974 if (val.tag() != .unreachable_value) continue; // comptime field
1944 if (!field_ty.hasCodeGenBits()) continue;
1975 if (!field_ty.hasRuntimeBits()) continue;
19451976
19461977 const field_align = field_ty.abiAlignment(target);
19471978 big_align = @maximum(big_align, field_align);
......@@ -1984,7 +2015,7 @@ pub const Type = extern union {
19842015 }
19852016
19862017 /// Asserts the type has the ABI size already resolved.
1987 /// Types that return false for hasCodeGenBits() return 0.
2018 /// Types that return false for hasRuntimeBits() return 0.
19882019 pub fn abiSize(self: Type, target: Target) u64 {
19892020 return switch (self.tag()) {
19902021 .fn_noreturn_no_args => unreachable, // represents machine code; not a pointer
......@@ -2071,24 +2102,8 @@ pub const Type = extern union {
20712102 .usize,
20722103 .@"anyframe",
20732104 .anyframe_T,
2074 => return @divExact(target.cpu.arch.ptrBitWidth(), 8),
2075
2076 .const_slice,
2077 .mut_slice,
2078 => {
2079 return @divExact(target.cpu.arch.ptrBitWidth(), 8) * 2;
2080 },
2081 .const_slice_u8,
2082 .const_slice_u8_sentinel_0,
2083 => return @divExact(target.cpu.arch.ptrBitWidth(), 8) * 2,
2084
20852105 .optional_single_const_pointer,
20862106 .optional_single_mut_pointer,
2087 => {
2088 if (!self.elemType().hasCodeGenBits()) return 1;
2089 return @divExact(target.cpu.arch.ptrBitWidth(), 8);
2090 },
2091
20922107 .single_const_pointer,
20932108 .single_mut_pointer,
20942109 .many_const_pointer,
......@@ -2100,6 +2115,12 @@ pub const Type = extern union {
21002115 .manyptr_const_u8_sentinel_0,
21012116 => return @divExact(target.cpu.arch.ptrBitWidth(), 8),
21022117
2118 .const_slice,
2119 .mut_slice,
2120 .const_slice_u8,
2121 .const_slice_u8_sentinel_0,
2122 => return @divExact(target.cpu.arch.ptrBitWidth(), 8) * 2,
2123
21032124 .pointer => switch (self.castTag(.pointer).?.data.size) {
21042125 .Slice => @divExact(target.cpu.arch.ptrBitWidth(), 8) * 2,
21052126 else => @divExact(target.cpu.arch.ptrBitWidth(), 8),
......@@ -2137,7 +2158,7 @@ pub const Type = extern union {
21372158 .optional => {
21382159 var buf: Payload.ElemType = undefined;
21392160 const child_type = self.optionalChild(&buf);
2140 if (!child_type.hasCodeGenBits()) return 1;
2161 if (!child_type.hasRuntimeBits()) return 1;
21412162
21422163 if (child_type.zigTypeTag() == .Pointer and !child_type.isCPtr() and !child_type.isSlice())
21432164 return @divExact(target.cpu.arch.ptrBitWidth(), 8);
......@@ -2151,11 +2172,11 @@ pub const Type = extern union {
21512172
21522173 .error_union => {
21532174 const data = self.castTag(.error_union).?.data;
2154 if (!data.error_set.hasCodeGenBits() and !data.payload.hasCodeGenBits()) {
2175 if (!data.error_set.hasRuntimeBits() and !data.payload.hasRuntimeBits()) {
21552176 return 0;
2156 } else if (!data.error_set.hasCodeGenBits()) {
2177 } else if (!data.error_set.hasRuntimeBits()) {
21572178 return data.payload.abiSize(target);
2158 } else if (!data.payload.hasCodeGenBits()) {
2179 } else if (!data.payload.hasRuntimeBits()) {
21592180 return data.error_set.abiSize(target);
21602181 }
21612182 const code_align = abiAlignment(data.error_set, target);
......@@ -2275,11 +2296,7 @@ pub const Type = extern union {
22752296 .optional_single_const_pointer,
22762297 .optional_single_mut_pointer,
22772298 => {
2278 if (ty.elemType().hasCodeGenBits()) {
2279 return target.cpu.arch.ptrBitWidth();
2280 } else {
2281 return 1;
2282 }
2299 return target.cpu.arch.ptrBitWidth();
22832300 },
22842301
22852302 .single_const_pointer,
......@@ -2289,11 +2306,7 @@ pub const Type = extern union {
22892306 .c_const_pointer,
22902307 .c_mut_pointer,
22912308 => {
2292 if (ty.elemType().hasCodeGenBits()) {
2293 return target.cpu.arch.ptrBitWidth();
2294 } else {
2295 return 0;
2296 }
2309 return target.cpu.arch.ptrBitWidth();
22972310 },
22982311
22992312 .pointer => switch (ty.castTag(.pointer).?.data.size) {
......@@ -2329,7 +2342,7 @@ pub const Type = extern union {
23292342 .optional => {
23302343 var buf: Payload.ElemType = undefined;
23312344 const child_type = ty.optionalChild(&buf);
2332 if (!child_type.hasCodeGenBits()) return 8;
2345 if (!child_type.hasRuntimeBits()) return 8;
23332346
23342347 if (child_type.zigTypeTag() == .Pointer and !child_type.isCPtr() and !child_type.isSlice())
23352348 return target.cpu.arch.ptrBitWidth();
......@@ -2343,11 +2356,11 @@ pub const Type = extern union {
23432356
23442357 .error_union => {
23452358 const payload = ty.castTag(.error_union).?.data;
2346 if (!payload.error_set.hasCodeGenBits() and !payload.payload.hasCodeGenBits()) {
2359 if (!payload.error_set.hasRuntimeBits() and !payload.payload.hasRuntimeBits()) {
23472360 return 0;
2348 } else if (!payload.error_set.hasCodeGenBits()) {
2361 } else if (!payload.error_set.hasRuntimeBits()) {
23492362 return payload.payload.bitSize(target);
2350 } else if (!payload.payload.hasCodeGenBits()) {
2363 } else if (!payload.payload.hasRuntimeBits()) {
23512364 return payload.error_set.bitSize(target);
23522365 }
23532366 @panic("TODO bitSize error union");
......@@ -2589,7 +2602,7 @@ pub const Type = extern union {
25892602 var buf: Payload.ElemType = undefined;
25902603 const child_type = self.optionalChild(&buf);
25912604 // optionals of zero sized pointers behave like bools
2592 if (!child_type.hasCodeGenBits()) return false;
2605 if (!child_type.hasRuntimeBits()) return false;
25932606 if (child_type.zigTypeTag() != .Pointer) return false;
25942607
25952608 const info = child_type.ptrInfo().data;
......@@ -2626,7 +2639,7 @@ pub const Type = extern union {
26262639 var buf: Payload.ElemType = undefined;
26272640 const child_type = self.optionalChild(&buf);
26282641 // optionals of zero sized types behave like bools, not pointers
2629 if (!child_type.hasCodeGenBits()) return false;
2642 if (!child_type.hasRuntimeBits()) return false;
26302643 if (child_type.zigTypeTag() != .Pointer) return false;
26312644
26322645 const info = child_type.ptrInfo().data;
......@@ -3494,7 +3507,7 @@ pub const Type = extern union {
34943507 },
34953508 .enum_nonexhaustive => {
34963509 const tag_ty = ty.castTag(.enum_nonexhaustive).?.data.tag_ty;
3497 if (!tag_ty.hasCodeGenBits()) {
3510 if (!tag_ty.hasRuntimeBits()) {
34983511 return Value.zero;
34993512 } else {
35003513 return null;
......@@ -3537,6 +3550,167 @@ pub const Type = extern union {
35373550 };
35383551 }
35393552
3553 /// During semantic analysis, instead call `Sema.typeRequiresComptime` which
3554 /// resolves field types rather than asserting they are already resolved.
3555 pub fn comptimeOnly(ty: Type) bool {
3556 return switch (ty.tag()) {
3557 .u1,
3558 .u8,
3559 .i8,
3560 .u16,
3561 .i16,
3562 .u32,
3563 .i32,
3564 .u64,
3565 .i64,
3566 .u128,
3567 .i128,
3568 .usize,
3569 .isize,
3570 .c_short,
3571 .c_ushort,
3572 .c_int,
3573 .c_uint,
3574 .c_long,
3575 .c_ulong,
3576 .c_longlong,
3577 .c_ulonglong,
3578 .c_longdouble,
3579 .f16,
3580 .f32,
3581 .f64,
3582 .f128,
3583 .anyopaque,
3584 .bool,
3585 .void,
3586 .anyerror,
3587 .noreturn,
3588 .@"anyframe",
3589 .@"null",
3590 .@"undefined",
3591 .atomic_order,
3592 .atomic_rmw_op,
3593 .calling_convention,
3594 .address_space,
3595 .float_mode,
3596 .reduce_op,
3597 .call_options,
3598 .prefetch_options,
3599 .export_options,
3600 .extern_options,
3601 .manyptr_u8,
3602 .manyptr_const_u8,
3603 .manyptr_const_u8_sentinel_0,
3604 .const_slice_u8,
3605 .const_slice_u8_sentinel_0,
3606 .anyerror_void_error_union,
3607 .empty_struct_literal,
3608 .empty_struct,
3609 .error_set,
3610 .error_set_single,
3611 .error_set_inferred,
3612 .error_set_merged,
3613 .@"opaque",
3614 .generic_poison,
3615 .array_u8,
3616 .array_u8_sentinel_0,
3617 .int_signed,
3618 .int_unsigned,
3619 .enum_simple,
3620 => false,
3621
3622 .single_const_pointer_to_comptime_int,
3623 .type,
3624 .comptime_int,
3625 .comptime_float,
3626 .enum_literal,
3627 .type_info,
3628 // These are function bodies, not function pointers.
3629 .fn_noreturn_no_args,
3630 .fn_void_no_args,
3631 .fn_naked_noreturn_no_args,
3632 .fn_ccc_void_no_args,
3633 .function,
3634 => true,
3635
3636 .var_args_param => unreachable,
3637 .inferred_alloc_mut => unreachable,
3638 .inferred_alloc_const => unreachable,
3639 .bound_fn => unreachable,
3640
3641 .array,
3642 .array_sentinel,
3643 .vector,
3644 => return ty.childType().comptimeOnly(),
3645
3646 .pointer,
3647 .single_const_pointer,
3648 .single_mut_pointer,
3649 .many_const_pointer,
3650 .many_mut_pointer,
3651 .c_const_pointer,
3652 .c_mut_pointer,
3653 .const_slice,
3654 .mut_slice,
3655 => {
3656 const child_ty = ty.childType();
3657 if (child_ty.zigTypeTag() == .Fn) {
3658 return false;
3659 } else {
3660 return child_ty.comptimeOnly();
3661 }
3662 },
3663
3664 .optional,
3665 .optional_single_mut_pointer,
3666 .optional_single_const_pointer,
3667 => {
3668 var buf: Type.Payload.ElemType = undefined;
3669 return ty.optionalChild(&buf).comptimeOnly();
3670 },
3671
3672 .tuple => {
3673 const tuple = ty.castTag(.tuple).?.data;
3674 for (tuple.types) |field_ty| {
3675 if (field_ty.comptimeOnly()) return true;
3676 }
3677 return false;
3678 },
3679
3680 .@"struct" => {
3681 const struct_obj = ty.castTag(.@"struct").?.data;
3682 switch (struct_obj.requires_comptime) {
3683 .wip, .unknown => unreachable, // This function asserts types already resolved.
3684 .no => return false,
3685 .yes => return true,
3686 }
3687 },
3688
3689 .@"union", .union_tagged => {
3690 const union_obj = ty.cast(Type.Payload.Union).?.data;
3691 switch (union_obj.requires_comptime) {
3692 .wip, .unknown => unreachable, // This function asserts types already resolved.
3693 .no => return false,
3694 .yes => return true,
3695 }
3696 },
3697
3698 .error_union => return ty.errorUnionPayload().comptimeOnly(),
3699 .anyframe_T => {
3700 const child_ty = ty.castTag(.anyframe_T).?.data;
3701 return child_ty.comptimeOnly();
3702 },
3703 .enum_numbered => {
3704 const tag_ty = ty.castTag(.enum_numbered).?.data.tag_ty;
3705 return tag_ty.comptimeOnly();
3706 },
3707 .enum_full, .enum_nonexhaustive => {
3708 const tag_ty = ty.cast(Type.Payload.EnumFull).?.data.tag_ty;
3709 return tag_ty.comptimeOnly();
3710 },
3711 };
3712 }
3713
35403714 pub fn isIndexable(ty: Type) bool {
35413715 return switch (ty.zigTypeTag()) {
35423716 .Array, .Vector => true,
......@@ -3814,7 +3988,7 @@ pub const Type = extern union {
38143988
38153989 const field = it.struct_obj.fields.values()[it.field];
38163990 defer it.field += 1;
3817 if (!field.ty.hasCodeGenBits()) {
3991 if (!field.ty.hasRuntimeBits()) {
38183992 return PackedFieldOffset{
38193993 .field = it.field,
38203994 .offset = it.offset,
......@@ -3883,7 +4057,7 @@ pub const Type = extern union {
38834057
38844058 const field = it.struct_obj.fields.values()[it.field];
38854059 defer it.field += 1;
3886 if (!field.ty.hasCodeGenBits())
4060 if (!field.ty.hasRuntimeBits())
38874061 return FieldOffset{ .field = it.field, .offset = it.offset };
38884062
38894063 const field_align = field.normalAlignment(it.target);
src/value.zig+62-5
......@@ -1225,7 +1225,7 @@ pub const Value = extern union {
12251225
12261226 /// Asserts the value is an integer and not undefined.
12271227 /// Returns the number of bits the value requires to represent stored in twos complement form.
1228 pub fn intBitCountTwosComp(self: Value) usize {
1228 pub fn intBitCountTwosComp(self: Value, target: Target) usize {
12291229 switch (self.tag()) {
12301230 .zero,
12311231 .bool_false,
......@@ -1244,6 +1244,15 @@ pub const Value = extern union {
12441244 .int_big_positive => return self.castTag(.int_big_positive).?.asBigInt().bitCountTwosComp(),
12451245 .int_big_negative => return self.castTag(.int_big_negative).?.asBigInt().bitCountTwosComp(),
12461246
1247 .decl_ref_mut,
1248 .extern_fn,
1249 .decl_ref,
1250 .function,
1251 .variable,
1252 .eu_payload_ptr,
1253 .opt_payload_ptr,
1254 => return target.cpu.arch.ptrBitWidth(),
1255
12471256 else => {
12481257 var buffer: BigIntSpace = undefined;
12491258 return self.toBigInt(&buffer).bitCountTwosComp();
......@@ -1333,6 +1342,20 @@ pub const Value = extern union {
13331342 return true;
13341343 },
13351344
1345 .decl_ref_mut,
1346 .extern_fn,
1347 .decl_ref,
1348 .function,
1349 .variable,
1350 => {
1351 const info = ty.intInfo(target);
1352 const ptr_bits = target.cpu.arch.ptrBitWidth();
1353 return switch (info.signedness) {
1354 .signed => info.bits > ptr_bits,
1355 .unsigned => info.bits >= ptr_bits,
1356 };
1357 },
1358
13361359 else => unreachable,
13371360 }
13381361 }
......@@ -1397,6 +1420,11 @@ pub const Value = extern union {
13971420
13981421 .one,
13991422 .bool_true,
1423 .decl_ref,
1424 .decl_ref_mut,
1425 .extern_fn,
1426 .function,
1427 .variable,
14001428 => .gt,
14011429
14021430 .int_u64 => std.math.order(lhs.castTag(.int_u64).?.data, 0),
......@@ -1417,10 +1445,18 @@ pub const Value = extern union {
14171445 pub fn order(lhs: Value, rhs: Value) std.math.Order {
14181446 const lhs_tag = lhs.tag();
14191447 const rhs_tag = rhs.tag();
1420 const lhs_is_zero = lhs_tag == .zero;
1421 const rhs_is_zero = rhs_tag == .zero;
1422 if (lhs_is_zero) return rhs.orderAgainstZero().invert();
1423 if (rhs_is_zero) return lhs.orderAgainstZero();
1448 const lhs_against_zero = lhs.orderAgainstZero();
1449 const rhs_against_zero = rhs.orderAgainstZero();
1450 switch (lhs_against_zero) {
1451 .lt => if (rhs_against_zero != .lt) return .lt,
1452 .eq => return rhs_against_zero.invert(),
1453 .gt => {},
1454 }
1455 switch (rhs_against_zero) {
1456 .lt => if (lhs_against_zero != .lt) return .gt,
1457 .eq => return lhs_against_zero,
1458 .gt => {},
1459 }
14241460
14251461 const lhs_float = lhs.isFloat();
14261462 const rhs_float = rhs.isFloat();
......@@ -1451,6 +1487,27 @@ pub const Value = extern union {
14511487 /// Asserts the value is comparable. Does not take a type parameter because it supports
14521488 /// comparisons between heterogeneous types.
14531489 pub fn compareHetero(lhs: Value, op: std.math.CompareOperator, rhs: Value) bool {
1490 if (lhs.pointerDecl()) |lhs_decl| {
1491 if (rhs.pointerDecl()) |rhs_decl| {
1492 switch (op) {
1493 .eq => return lhs_decl == rhs_decl,
1494 .neq => return lhs_decl != rhs_decl,
1495 else => {},
1496 }
1497 } else {
1498 switch (op) {
1499 .eq => return false,
1500 .neq => return true,
1501 else => {},
1502 }
1503 }
1504 } else if (rhs.pointerDecl()) |_| {
1505 switch (op) {
1506 .eq => return false,
1507 .neq => return true,
1508 else => {},
1509 }
1510 }
14541511 return order(lhs, rhs).compare(op);
14551512 }
14561513
test/behavior/cast_llvm.zig+5-1
......@@ -155,10 +155,14 @@ test "implicit cast *[0]T to E![]const u8" {
155155}
156156
157157var global_array: [4]u8 = undefined;
158test "cast from array reference to fn" {
158test "cast from array reference to fn: comptime fn ptr" {
159159 const f = @ptrCast(*const fn () callconv(.C) void, &global_array);
160160 try expect(@ptrToInt(f) == @ptrToInt(&global_array));
161161}
162test "cast from array reference to fn: runtime fn ptr" {
163 var f = @ptrCast(*const fn () callconv(.C) void, &global_array);
164 try expect(@ptrToInt(f) == @ptrToInt(&global_array));
165}
162166
163167test "*const [N]null u8 to ?[]const u8" {
164168 const S = struct {
test/stage2/arm.zig+1-1
......@@ -751,7 +751,7 @@ pub fn addCases(ctx: *TestContext) !void {
751751 {
752752 var case = ctx.exe("function pointers", linux_arm);
753753 case.addCompareOutput(
754 \\const PrintFn = fn () void;
754 \\const PrintFn = *const fn () void;
755755 \\
756756 \\pub fn main() void {
757757 \\ var printFn: PrintFn = stopSayingThat;