authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-09-03 15:48:28+03:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-09-03 15:48:28+03:00
logb7d5582dede8f4cae341365ac9c47c840bd80eff
tree76c5e13a11b133f44f096649be9d35ac2afe7f2a
parent10e11b60e56941cb664648dcebfd4db3d2efed30
parentc7884af063791211544c6595a4900bbfcd5d96b6
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #12723 from Vexu/stage2-fixes

Stage2 fixes

35 files changed, 558 insertions(+), 255 deletions(-)

src/AstGen.zig+1-1
...@@ -5127,7 +5127,7 @@ fn tryExpr(...@@ -5127,7 +5127,7 @@ fn tryExpr(
5127 else => .none,5127 else => .none,
5128 };5128 };
5129 // This could be a pointer or value depending on the `rl` parameter.5129 // This could be a pointer or value depending on the `rl` parameter.
5130 const operand = try expr(parent_gz, scope, operand_rl, operand_node);5130 const operand = try reachableExpr(parent_gz, scope, operand_rl, operand_node, node);
5131 const is_inline = parent_gz.force_comptime;5131 const is_inline = parent_gz.force_comptime;
5132 const is_inline_bit = @as(u2, @boolToInt(is_inline));5132 const is_inline_bit = @as(u2, @boolToInt(is_inline));
5133 const is_ptr_bit = @as(u2, @boolToInt(operand_rl == .ref)) << 1;5133 const is_ptr_bit = @as(u2, @boolToInt(operand_rl == .ref)) << 1;
src/Module.zig+1-1
...@@ -4635,7 +4635,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {...@@ -4635,7 +4635,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
4635 decl.analysis = .complete;4635 decl.analysis = .complete;
4636 decl.generation = mod.generation;4636 decl.generation = mod.generation;
46374637
4638 const has_runtime_bits = try sema.fnHasRuntimeBits(&block_scope, ty_src, decl.ty);4638 const has_runtime_bits = try sema.fnHasRuntimeBits(decl.ty);
46394639
4640 if (has_runtime_bits) {4640 if (has_runtime_bits) {
4641 // We don't fully codegen the decl until later, but we do need to reserve a global4641 // We don't fully codegen the decl until later, but we do need to reserve a global
src/Sema.zig+125-62
...@@ -2565,7 +2565,7 @@ fn zirEnumDecl(...@@ -2565,7 +2565,7 @@ fn zirEnumDecl(
2565 }2565 }
2566 }2566 }
25672567
2568 if (small.nonexhaustive) {2568 if (small.nonexhaustive and enum_obj.tag_ty.zigTypeTag() != .ComptimeInt) {
2569 if (fields_len > 1 and std.math.log2_int(u64, fields_len) == enum_obj.tag_ty.bitSize(sema.mod.getTarget())) {2569 if (fields_len > 1 and std.math.log2_int(u64, fields_len) == enum_obj.tag_ty.bitSize(sema.mod.getTarget())) {
2570 return sema.fail(block, src, "non-exhaustive enum specifies every value", .{});2570 return sema.fail(block, src, "non-exhaustive enum specifies every value", .{});
2571 }2571 }
...@@ -2586,6 +2586,7 @@ fn zirEnumDecl(...@@ -2586,6 +2586,7 @@ fn zirEnumDecl(
2586 var cur_bit_bag: u32 = undefined;2586 var cur_bit_bag: u32 = undefined;
2587 var field_i: u32 = 0;2587 var field_i: u32 = 0;
2588 var last_tag_val: ?Value = null;2588 var last_tag_val: ?Value = null;
2589 var tag_val_buf: Value.Payload.U64 = undefined;
2589 while (field_i < fields_len) : (field_i += 1) {2590 while (field_i < fields_len) : (field_i += 1) {
2590 if (field_i % 32 == 0) {2591 if (field_i % 32 == 0) {
2591 cur_bit_bag = sema.code.extra[bit_bag_index];2592 cur_bit_bag = sema.code.extra[bit_bag_index];
...@@ -2641,6 +2642,21 @@ fn zirEnumDecl(...@@ -2641,6 +2642,21 @@ fn zirEnumDecl(
2641 .ty = enum_obj.tag_ty,2642 .ty = enum_obj.tag_ty,
2642 .mod = mod,2643 .mod = mod,
2643 });2644 });
2645 } else {
2646 tag_val_buf = .{
2647 .base = .{ .tag = .int_u64 },
2648 .data = field_i,
2649 };
2650 last_tag_val = Value.initPayload(&tag_val_buf.base);
2651 }
2652
2653 if (!(try sema.intFitsInType(block, src, last_tag_val.?, enum_obj.tag_ty, null))) {
2654 const tree = try sema.getAstTree(block);
2655 const field_src = enumFieldSrcLoc(sema.mod.declPtr(block.src_decl), tree.*, src.node_offset.x, field_i);
2656 const msg = try sema.errMsg(block, field_src, "enumeration value '{}' too large for type '{}'", .{
2657 last_tag_val.?.fmtValue(enum_obj.tag_ty, mod), enum_obj.tag_ty.fmt(mod),
2658 });
2659 return sema.failWithOwnedErrorMsg(msg);
2644 }2660 }
2645 }2661 }
2646 return decl_val;2662 return decl_val;
...@@ -2849,7 +2865,7 @@ fn zirRetPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -2849,7 +2865,7 @@ fn zirRetPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
2849 const inst_data = sema.code.instructions.items(.data)[inst].node;2865 const inst_data = sema.code.instructions.items(.data)[inst].node;
2850 const src = LazySrcLoc.nodeOffset(inst_data);2866 const src = LazySrcLoc.nodeOffset(inst_data);
28512867
2852 if (block.is_comptime or try sema.typeRequiresComptime(block, src, sema.fn_ret_ty)) {2868 if (block.is_comptime or try sema.typeRequiresComptime(sema.fn_ret_ty)) {
2853 const fn_ret_ty = try sema.resolveTypeFields(block, src, sema.fn_ret_ty);2869 const fn_ret_ty = try sema.resolveTypeFields(block, src, sema.fn_ret_ty);
2854 return sema.analyzeComptimeAlloc(block, fn_ret_ty, 0, src);2870 return sema.analyzeComptimeAlloc(block, fn_ret_ty, 0, src);
2855 }2871 }
...@@ -5040,7 +5056,7 @@ pub fn analyzeExport(...@@ -5040,7 +5056,7 @@ pub fn analyzeExport(
5040 try mod.ensureDeclAnalyzed(exported_decl_index);5056 try mod.ensureDeclAnalyzed(exported_decl_index);
5041 const exported_decl = mod.declPtr(exported_decl_index);5057 const exported_decl = mod.declPtr(exported_decl_index);
50425058
5043 if (!sema.validateExternType(exported_decl.ty, .other)) {5059 if (!try sema.validateExternType(block, src, exported_decl.ty, .other)) {
5044 const msg = msg: {5060 const msg = msg: {
5045 const msg = try sema.errMsg(block, src, "unable to export type '{}'", .{exported_decl.ty.fmt(sema.mod)});5061 const msg = try sema.errMsg(block, src, "unable to export type '{}'", .{exported_decl.ty.fmt(sema.mod)});
5046 errdefer msg.destroy(sema.gpa);5062 errdefer msg.destroy(sema.gpa);
...@@ -5569,7 +5585,11 @@ fn zirCall(...@@ -5569,7 +5585,11 @@ fn zirCall(
5569 const param_ty_inst = try sema.addType(param_ty);5585 const param_ty_inst = try sema.addType(param_ty);
5570 try sema.inst_map.put(sema.gpa, inst, param_ty_inst);5586 try sema.inst_map.put(sema.gpa, inst, param_ty_inst);
55715587
5572 resolved_args[arg_index] = try sema.resolveBody(block, args_body[arg_start..arg_end], inst);5588 const resolved = try sema.resolveBody(block, args_body[arg_start..arg_end], inst);
5589 if (sema.typeOf(resolved).zigTypeTag() == .NoReturn) {
5590 return resolved;
5591 }
5592 resolved_args[arg_index] = resolved;
5573 }5593 }
55745594
5575 return sema.analyzeCall(block, func, func_src, call_src, modifier, ensure_result_used, resolved_args, bound_arg_src);5595 return sema.analyzeCall(block, func, func_src, call_src, modifier, ensure_result_used, resolved_args, bound_arg_src);
...@@ -5768,7 +5788,7 @@ fn analyzeCall(...@@ -5768,7 +5788,7 @@ fn analyzeCall(
5768 var is_comptime_call = block.is_comptime or modifier == .compile_time;5788 var is_comptime_call = block.is_comptime or modifier == .compile_time;
5769 var comptime_only_ret_ty = false;5789 var comptime_only_ret_ty = false;
5770 if (!is_comptime_call) {5790 if (!is_comptime_call) {
5771 if (sema.typeRequiresComptime(block, func_src, func_ty_info.return_type)) |ct| {5791 if (sema.typeRequiresComptime(func_ty_info.return_type)) |ct| {
5772 is_comptime_call = ct;5792 is_comptime_call = ct;
5773 comptime_only_ret_ty = ct;5793 comptime_only_ret_ty = ct;
5774 } else |err| switch (err) {5794 } else |err| switch (err) {
...@@ -6047,7 +6067,7 @@ fn analyzeCall(...@@ -6047,7 +6067,7 @@ fn analyzeCall(
6047 break :result try sema.analyzeBlockBody(block, call_src, &child_block, merges);6067 break :result try sema.analyzeBlockBody(block, call_src, &child_block, merges);
6048 };6068 };
60496069
6050 if (!is_comptime_call) {6070 if (!is_comptime_call and sema.typeOf(result).zigTypeTag() != .NoReturn) {
6051 try sema.emitDbgInline(6071 try sema.emitDbgInline(
6052 block,6072 block,
6053 module_fn,6073 module_fn,
...@@ -6206,7 +6226,7 @@ fn analyzeInlineCallArg(...@@ -6206,7 +6226,7 @@ fn analyzeInlineCallArg(
6206 const param_ty = try sema.analyzeAsType(param_block, param_src, param_ty_inst);6226 const param_ty = try sema.analyzeAsType(param_block, param_src, param_ty_inst);
6207 new_fn_info.param_types[arg_i.*] = param_ty;6227 new_fn_info.param_types[arg_i.*] = param_ty;
6208 const uncasted_arg = uncasted_args[arg_i.*];6228 const uncasted_arg = uncasted_args[arg_i.*];
6209 if (try sema.typeRequiresComptime(arg_block, arg_src, param_ty)) {6229 if (try sema.typeRequiresComptime(param_ty)) {
6210 _ = sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "argument to parameter with comptime only type must be comptime known") catch |err| {6230 _ = sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "argument to parameter with comptime only type must be comptime known") catch |err| {
6211 if (err == error.AnalysisFail and sema.err != null) {6231 if (err == error.AnalysisFail and sema.err != null) {
6212 try sema.addComptimeReturnTypeNote(arg_block, func, func_src, ret_ty, sema.err.?, comptime_only_ret_ty);6232 try sema.addComptimeReturnTypeNote(arg_block, func, func_src, ret_ty, sema.err.?, comptime_only_ret_ty);
...@@ -6308,7 +6328,7 @@ fn analyzeGenericCallArg(...@@ -6308,7 +6328,7 @@ fn analyzeGenericCallArg(
6308) !void {6328) !void {
6309 const is_runtime = comptime_arg.val.tag() == .generic_poison and6329 const is_runtime = comptime_arg.val.tag() == .generic_poison and
6310 comptime_arg.ty.hasRuntimeBits() and6330 comptime_arg.ty.hasRuntimeBits() and
6311 !(try sema.typeRequiresComptime(block, arg_src, comptime_arg.ty));6331 !(try sema.typeRequiresComptime(comptime_arg.ty));
6312 if (is_runtime) {6332 if (is_runtime) {
6313 const param_ty = new_fn_info.param_types[runtime_i.*];6333 const param_ty = new_fn_info.param_types[runtime_i.*];
6314 const casted_arg = try sema.coerce(block, param_ty, uncasted_arg, arg_src);6334 const casted_arg = try sema.coerce(block, param_ty, uncasted_arg, arg_src);
...@@ -6573,7 +6593,7 @@ fn instantiateGenericCall(...@@ -6573,7 +6593,7 @@ fn instantiateGenericCall(
6573 }6593 }
6574 } else if (is_anytype) {6594 } else if (is_anytype) {
6575 const arg_ty = sema.typeOf(arg);6595 const arg_ty = sema.typeOf(arg);
6576 if (try sema.typeRequiresComptime(block, .unneeded, arg_ty)) {6596 if (try sema.typeRequiresComptime(arg_ty)) {
6577 const arg_val = try sema.resolveConstValue(block, .unneeded, arg, undefined);6597 const arg_val = try sema.resolveConstValue(block, .unneeded, arg, undefined);
6578 const child_arg = try child_sema.addConstant(arg_ty, arg_val);6598 const child_arg = try child_sema.addConstant(arg_ty, arg_val);
6579 child_sema.inst_map.putAssumeCapacityNoClobber(inst, child_arg);6599 child_sema.inst_map.putAssumeCapacityNoClobber(inst, child_arg);
...@@ -6626,7 +6646,7 @@ fn instantiateGenericCall(...@@ -6626,7 +6646,7 @@ fn instantiateGenericCall(
6626 const arg = child_sema.inst_map.get(inst).?;6646 const arg = child_sema.inst_map.get(inst).?;
6627 const copied_arg_ty = try child_sema.typeOf(arg).copy(new_decl_arena_allocator);6647 const copied_arg_ty = try child_sema.typeOf(arg).copy(new_decl_arena_allocator);
66286648
6629 if (try sema.typeRequiresComptime(block, .unneeded, copied_arg_ty)) {6649 if (try sema.typeRequiresComptime(copied_arg_ty)) {
6630 is_comptime = true;6650 is_comptime = true;
6631 }6651 }
66326652
...@@ -6657,7 +6677,7 @@ fn instantiateGenericCall(...@@ -6657,7 +6677,7 @@ fn instantiateGenericCall(
6657 // If the call evaluated to a return type that requires comptime, never mind6677 // If the call evaluated to a return type that requires comptime, never mind
6658 // our generic instantiation. Instead we need to perform a comptime call.6678 // our generic instantiation. Instead we need to perform a comptime call.
6659 const new_fn_info = new_decl.ty.fnInfo();6679 const new_fn_info = new_decl.ty.fnInfo();
6660 if (try sema.typeRequiresComptime(block, call_src, new_fn_info.return_type)) {6680 if (try sema.typeRequiresComptime(new_fn_info.return_type)) {
6661 return error.ComptimeReturn;6681 return error.ComptimeReturn;
6662 }6682 }
6663 // Similarly, if the call evaluated to a generic type we need to instead6683 // Similarly, if the call evaluated to a generic type we need to instead
...@@ -7838,7 +7858,7 @@ fn funcCommon(...@@ -7838,7 +7858,7 @@ fn funcCommon(
7838 }7858 }
78397859
7840 var ret_ty_requires_comptime = false;7860 var ret_ty_requires_comptime = false;
7841 const ret_poison = if (sema.typeRequiresComptime(block, ret_ty_src, bare_return_type)) |ret_comptime| rp: {7861 const ret_poison = if (sema.typeRequiresComptime(bare_return_type)) |ret_comptime| rp: {
7842 ret_ty_requires_comptime = ret_comptime;7862 ret_ty_requires_comptime = ret_comptime;
7843 break :rp bare_return_type.tag() == .generic_poison;7863 break :rp bare_return_type.tag() == .generic_poison;
7844 } else |err| switch (err) {7864 } else |err| switch (err) {
...@@ -7876,7 +7896,7 @@ fn funcCommon(...@@ -7876,7 +7896,7 @@ fn funcCommon(
7876 };7896 };
7877 return sema.failWithOwnedErrorMsg(msg);7897 return sema.failWithOwnedErrorMsg(msg);
7878 }7898 }
7879 if (!Type.fnCallingConventionAllowsZigTypes(cc_workaround) and !sema.validateExternType(return_type, .ret_ty)) {7899 if (!Type.fnCallingConventionAllowsZigTypes(cc_workaround) and !try sema.validateExternType(block, ret_ty_src, return_type, .ret_ty)) {
7880 const msg = msg: {7900 const msg = msg: {
7881 const msg = try sema.errMsg(block, ret_ty_src, "return type '{}' not allowed in function with calling convention '{s}'", .{7901 const msg = try sema.errMsg(block, ret_ty_src, "return type '{}' not allowed in function with calling convention '{s}'", .{
7882 return_type.fmt(sema.mod), @tagName(cc_workaround),7902 return_type.fmt(sema.mod), @tagName(cc_workaround),
...@@ -8072,7 +8092,7 @@ fn analyzeParameter(...@@ -8072,7 +8092,7 @@ fn analyzeParameter(
8072 cc: std.builtin.CallingConvention,8092 cc: std.builtin.CallingConvention,
8073 has_body: bool,8093 has_body: bool,
8074) !void {8094) !void {
8075 const requires_comptime = try sema.typeRequiresComptime(block, param_src, param.ty);8095 const requires_comptime = try sema.typeRequiresComptime(param.ty);
8076 comptime_params[i] = param.is_comptime or requires_comptime;8096 comptime_params[i] = param.is_comptime or requires_comptime;
8077 const this_generic = param.ty.tag() == .generic_poison;8097 const this_generic = param.ty.tag() == .generic_poison;
8078 is_generic.* = is_generic.* or this_generic;8098 is_generic.* = is_generic.* or this_generic;
...@@ -8095,7 +8115,7 @@ fn analyzeParameter(...@@ -8095,7 +8115,7 @@ fn analyzeParameter(
8095 };8115 };
8096 return sema.failWithOwnedErrorMsg(msg);8116 return sema.failWithOwnedErrorMsg(msg);
8097 }8117 }
8098 if (!Type.fnCallingConventionAllowsZigTypes(cc) and !sema.validateExternType(param.ty, .param_ty)) {8118 if (!Type.fnCallingConventionAllowsZigTypes(cc) and !try sema.validateExternType(block, param_src, param.ty, .param_ty)) {
8099 const msg = msg: {8119 const msg = msg: {
8100 const msg = try sema.errMsg(block, param_src, "parameter of type '{}' not allowed in function with calling convention '{s}'", .{8120 const msg = try sema.errMsg(block, param_src, "parameter of type '{}' not allowed in function with calling convention '{s}'", .{
8101 param.ty.fmt(sema.mod), @tagName(cc),8121 param.ty.fmt(sema.mod), @tagName(cc),
...@@ -8177,7 +8197,7 @@ fn zirParam(...@@ -8177,7 +8197,7 @@ fn zirParam(
8177 }8197 }
8178 };8198 };
8179 const is_comptime = comptime_syntax or8199 const is_comptime = comptime_syntax or
8180 try sema.typeRequiresComptime(block, src, param_ty);8200 try sema.typeRequiresComptime(param_ty);
8181 if (sema.inst_map.get(inst)) |arg| {8201 if (sema.inst_map.get(inst)) |arg| {
8182 if (is_comptime) {8202 if (is_comptime) {
8183 // We have a comptime value for this parameter so it should be elided from the8203 // We have a comptime value for this parameter so it should be elided from the
...@@ -8237,7 +8257,7 @@ fn zirParamAnytype(...@@ -8237,7 +8257,7 @@ fn zirParamAnytype(
82378257
8238 if (sema.inst_map.get(inst)) |air_ref| {8258 if (sema.inst_map.get(inst)) |air_ref| {
8239 const param_ty = sema.typeOf(air_ref);8259 const param_ty = sema.typeOf(air_ref);
8240 if (comptime_syntax or try sema.typeRequiresComptime(block, src, param_ty)) {8260 if (comptime_syntax or try sema.typeRequiresComptime(param_ty)) {
8241 // We have a comptime value for this parameter so it should be elided from the8261 // We have a comptime value for this parameter so it should be elided from the
8242 // function type of the function instruction in this block.8262 // function type of the function instruction in this block.
8243 return;8263 return;
...@@ -15565,7 +15585,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -15565,7 +15585,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
15565 } else if (inst_data.size == .Many and elem_ty.zigTypeTag() == .Opaque) {15585 } else if (inst_data.size == .Many and elem_ty.zigTypeTag() == .Opaque) {
15566 return sema.fail(block, elem_ty_src, "unknown-length pointer to opaque not allowed", .{});15586 return sema.fail(block, elem_ty_src, "unknown-length pointer to opaque not allowed", .{});
15567 } else if (inst_data.size == .C) {15587 } else if (inst_data.size == .C) {
15568 if (!sema.validateExternType(elem_ty, .other)) {15588 if (!try sema.validateExternType(block, elem_ty_src, elem_ty, .other)) {
15569 const msg = msg: {15589 const msg = msg: {
15570 const msg = try sema.errMsg(block, elem_ty_src, "C pointers cannot point to non-C-ABI-compatible type '{}'", .{elem_ty.fmt(sema.mod)});15590 const msg = try sema.errMsg(block, elem_ty_src, "C pointers cannot point to non-C-ABI-compatible type '{}'", .{elem_ty.fmt(sema.mod)});
15571 errdefer msg.destroy(sema.gpa);15591 errdefer msg.destroy(sema.gpa);
...@@ -16663,7 +16683,7 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in...@@ -16663,7 +16683,7 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in
16663 } else if (ptr_size == .Many and elem_ty.zigTypeTag() == .Opaque) {16683 } else if (ptr_size == .Many and elem_ty.zigTypeTag() == .Opaque) {
16664 return sema.fail(block, src, "unknown-length pointer to opaque not allowed", .{});16684 return sema.fail(block, src, "unknown-length pointer to opaque not allowed", .{});
16665 } else if (ptr_size == .C) {16685 } else if (ptr_size == .C) {
16666 if (!sema.validateExternType(elem_ty, .other)) {16686 if (!try sema.validateExternType(block, src, elem_ty, .other)) {
16667 const msg = msg: {16687 const msg = msg: {
16668 const msg = try sema.errMsg(block, src, "C pointers cannot point to non-C-ABI-compatible type '{}'", .{elem_ty.fmt(sema.mod)});16688 const msg = try sema.errMsg(block, src, "C pointers cannot point to non-C-ABI-compatible type '{}'", .{elem_ty.fmt(sema.mod)});
16669 errdefer msg.destroy(sema.gpa);16689 errdefer msg.destroy(sema.gpa);
...@@ -17501,7 +17521,7 @@ fn zirIntToFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -17501,7 +17521,7 @@ fn zirIntToFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
1750117521
17502 if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |val| {17522 if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |val| {
17503 const target = sema.mod.getTarget();17523 const target = sema.mod.getTarget();
17504 const result_val = try val.intToFloat(sema.arena, operand_ty, dest_ty, target);17524 const result_val = try val.intToFloatAdvanced(sema.arena, operand_ty, dest_ty, target, sema.kit(block, operand_src));
17505 return sema.addConstant(dest_ty, result_val);17525 return sema.addConstant(dest_ty, result_val);
17506 } else if (dest_ty.zigTypeTag() == .ComptimeFloat) {17526 } else if (dest_ty.zigTypeTag() == .ComptimeFloat) {
17507 return sema.failWithNeededComptime(block, operand_src, "value being casted to 'comptime_float' must be comptime known");17527 return sema.failWithNeededComptime(block, operand_src, "value being casted to 'comptime_float' must be comptime known");
...@@ -20345,12 +20365,13 @@ fn validateRunTimeType(...@@ -20345,12 +20365,13 @@ fn validateRunTimeType(
20345 .Int,20365 .Int,
20346 .Float,20366 .Float,
20347 .ErrorSet,20367 .ErrorSet,
20348 .Enum,
20349 .Frame,20368 .Frame,
20350 .AnyFrame,20369 .AnyFrame,
20351 .Void,20370 .Void,
20352 => return true,20371 => return true,
2035320372
20373 .Enum => return !(try sema.typeRequiresComptime(ty)),
20374
20354 .BoundFn,20375 .BoundFn,
20355 .ComptimeFloat,20376 .ComptimeFloat,
20356 .ComptimeInt,20377 .ComptimeInt,
...@@ -20383,7 +20404,7 @@ fn validateRunTimeType(...@@ -20383,7 +20404,7 @@ fn validateRunTimeType(
2038320404
20384 .Struct, .Union => {20405 .Struct, .Union => {
20385 const resolved_ty = try sema.resolveTypeFields(block, src, ty);20406 const resolved_ty = try sema.resolveTypeFields(block, src, ty);
20386 const needs_comptime = try sema.typeRequiresComptime(block, src, resolved_ty);20407 const needs_comptime = try sema.typeRequiresComptime(resolved_ty);
20387 return !needs_comptime;20408 return !needs_comptime;
20388 },20409 },
20389 };20410 };
...@@ -20491,7 +20512,7 @@ fn explainWhyTypeIsComptimeInner(...@@ -20491,7 +20512,7 @@ fn explainWhyTypeIsComptimeInner(
20491 .range = .type,20512 .range = .type,
20492 });20513 });
2049320514
20494 if (try sema.typeRequiresComptime(block, src, field.ty)) {20515 if (try sema.typeRequiresComptime(field.ty)) {
20495 try mod.errNoteNonLazy(field_src_loc, msg, "struct requires comptime because of this field", .{});20516 try mod.errNoteNonLazy(field_src_loc, msg, "struct requires comptime because of this field", .{});
20496 try sema.explainWhyTypeIsComptimeInner(block, src, msg, field_src_loc, field.ty, type_set);20517 try sema.explainWhyTypeIsComptimeInner(block, src, msg, field_src_loc, field.ty, type_set);
20497 }20518 }
...@@ -20511,7 +20532,7 @@ fn explainWhyTypeIsComptimeInner(...@@ -20511,7 +20532,7 @@ fn explainWhyTypeIsComptimeInner(
20511 .range = .type,20532 .range = .type,
20512 });20533 });
2051320534
20514 if (try sema.typeRequiresComptime(block, src, field.ty)) {20535 if (try sema.typeRequiresComptime(field.ty)) {
20515 try mod.errNoteNonLazy(field_src_loc, msg, "union requires comptime because of this field", .{});20536 try mod.errNoteNonLazy(field_src_loc, msg, "union requires comptime because of this field", .{});
20516 try sema.explainWhyTypeIsComptimeInner(block, src, msg, field_src_loc, field.ty, type_set);20537 try sema.explainWhyTypeIsComptimeInner(block, src, msg, field_src_loc, field.ty, type_set);
20517 }20538 }
...@@ -20530,7 +20551,14 @@ const ExternPosition = enum {...@@ -20530,7 +20551,14 @@ const ExternPosition = enum {
2053020551
20531/// Returns true if `ty` is allowed in extern types.20552/// Returns true if `ty` is allowed in extern types.
20532/// Does *NOT* require `ty` to be resolved in any way.20553/// Does *NOT* require `ty` to be resolved in any way.
20533fn validateExternType(sema: *Sema, ty: Type, position: ExternPosition) bool {20554/// Calls `resolveTypeLayout` for packed containers.
20555fn validateExternType(
20556 sema: *Sema,
20557 block: *Block,
20558 src: LazySrcLoc,
20559 ty: Type,
20560 position: ExternPosition,
20561) !bool {
20534 switch (ty.zigTypeTag()) {20562 switch (ty.zigTypeTag()) {
20535 .Type,20563 .Type,
20536 .ComptimeFloat,20564 .ComptimeFloat,
...@@ -20558,17 +20586,25 @@ fn validateExternType(sema: *Sema, ty: Type, position: ExternPosition) bool {...@@ -20558,17 +20586,25 @@ fn validateExternType(sema: *Sema, ty: Type, position: ExternPosition) bool {
20558 .Fn => return !Type.fnCallingConventionAllowsZigTypes(ty.fnCallingConvention()),20586 .Fn => return !Type.fnCallingConventionAllowsZigTypes(ty.fnCallingConvention()),
20559 .Enum => {20587 .Enum => {
20560 var buf: Type.Payload.Bits = undefined;20588 var buf: Type.Payload.Bits = undefined;
20561 return sema.validateExternType(ty.intTagType(&buf), position);20589 return sema.validateExternType(block, src, ty.intTagType(&buf), position);
20562 },20590 },
20563 .Struct, .Union => switch (ty.containerLayout()) {20591 .Struct, .Union => switch (ty.containerLayout()) {
20564 .Extern, .Packed => return true,20592 .Extern => return true,
20565 else => return false,20593 .Packed => {
20594 const target = sema.mod.getTarget();
20595 const bit_size = try ty.bitSizeAdvanced(target, sema.kit(block, src));
20596 switch (bit_size) {
20597 8, 16, 32, 64, 128 => return true,
20598 else => return false,
20599 }
20600 },
20601 .Auto => return false,
20566 },20602 },
20567 .Array => {20603 .Array => {
20568 if (position == .ret_ty or position == .param_ty) return false;20604 if (position == .ret_ty or position == .param_ty) return false;
20569 return sema.validateExternType(ty.elemType2(), .other);20605 return sema.validateExternType(block, src, ty.elemType2(), .other);
20570 },20606 },
20571 .Vector => return sema.validateExternType(ty.elemType2(), .other),20607 .Vector => return sema.validateExternType(block, src, ty.elemType2(), .other),
20572 .Optional => return ty.isPtrLikeOptional(),20608 .Optional => return ty.isPtrLikeOptional(),
20573 }20609 }
20574}20610}
...@@ -20620,8 +20656,8 @@ fn explainWhyTypeIsNotExtern(...@@ -20620,8 +20656,8 @@ fn explainWhyTypeIsNotExtern(
20620 try mod.errNoteNonLazy(src_loc, msg, "enum tag type '{}' is not extern compatible", .{tag_ty.fmt(sema.mod)});20656 try mod.errNoteNonLazy(src_loc, msg, "enum tag type '{}' is not extern compatible", .{tag_ty.fmt(sema.mod)});
20621 try sema.explainWhyTypeIsNotExtern(msg, src_loc, tag_ty, position);20657 try sema.explainWhyTypeIsNotExtern(msg, src_loc, tag_ty, position);
20622 },20658 },
20623 .Struct => try mod.errNoteNonLazy(src_loc, msg, "only structs with packed or extern layout are extern compatible", .{}),20659 .Struct => try mod.errNoteNonLazy(src_loc, msg, "only extern structs and ABI sized packed structs are extern compatible", .{}),
20624 .Union => try mod.errNoteNonLazy(src_loc, msg, "only unions with packed or extern layout are extern compatible", .{}),20660 .Union => try mod.errNoteNonLazy(src_loc, msg, "only extern unions and ABI sized packed unions are extern compatible", .{}),
20625 .Array => {20661 .Array => {
20626 if (position == .ret_ty) {20662 if (position == .ret_ty) {
20627 return mod.errNoteNonLazy(src_loc, msg, "arrays are not allowed as a return type", .{});20663 return mod.errNoteNonLazy(src_loc, msg, "arrays are not allowed as a return type", .{});
...@@ -23000,7 +23036,7 @@ fn coerceExtra(...@@ -23000,7 +23036,7 @@ fn coerceExtra(
23000 }23036 }
23001 break :int;23037 break :int;
23002 };23038 };
23003 const result_val = try val.intToFloat(sema.arena, inst_ty, dest_ty, target);23039 const result_val = try val.intToFloatAdvanced(sema.arena, inst_ty, dest_ty, target, sema.kit(block, inst_src));
23004 // TODO implement this compile error23040 // TODO implement this compile error
23005 //const int_again_val = try result_val.floatToInt(sema.arena, inst_ty);23041 //const int_again_val = try result_val.floatToInt(sema.arena, inst_ty);
23006 //if (!int_again_val.eql(val, inst_ty, mod)) {23042 //if (!int_again_val.eql(val, inst_ty, mod)) {
...@@ -23424,8 +23460,11 @@ const InMemoryCoercionResult = union(enum) {...@@ -23424,8 +23460,11 @@ const InMemoryCoercionResult = union(enum) {
23424 var index: u6 = 0;23460 var index: u6 = 0;
23425 var actual_noalias = false;23461 var actual_noalias = false;
23426 while (true) : (index += 1) {23462 while (true) : (index += 1) {
23427 if (param.actual << index != param.wanted << index) {23463 const actual = @truncate(u1, param.actual >> index);
23428 actual_noalias = (param.actual << index) == (1 << 31);23464 const wanted = @truncate(u1, param.wanted >> index);
23465 if (actual != wanted) {
23466 actual_noalias = actual == 1;
23467 break;
23429 }23468 }
23430 }23469 }
23431 if (!actual_noalias) {23470 if (!actual_noalias) {
...@@ -23919,7 +23958,7 @@ fn coerceInMemoryAllowedFns(...@@ -23919,7 +23958,7 @@ fn coerceInMemoryAllowedFns(
2391923958
23920 if (dest_info.noalias_bits != src_info.noalias_bits) {23959 if (dest_info.noalias_bits != src_info.noalias_bits) {
23921 return InMemoryCoercionResult{ .fn_param_noalias = .{23960 return InMemoryCoercionResult{ .fn_param_noalias = .{
23922 .actual = dest_info.noalias_bits,23961 .actual = src_info.noalias_bits,
23923 .wanted = dest_info.noalias_bits,23962 .wanted = dest_info.noalias_bits,
23924 } };23963 } };
23925 }23964 }
...@@ -24077,16 +24116,40 @@ fn coerceVarArgParam(...@@ -24077,16 +24116,40 @@ fn coerceVarArgParam(
24077 inst: Air.Inst.Ref,24116 inst: Air.Inst.Ref,
24078 inst_src: LazySrcLoc,24117 inst_src: LazySrcLoc,
24079) !Air.Inst.Ref {24118) !Air.Inst.Ref {
24080 const inst_ty = sema.typeOf(inst);
24081 if (block.is_typeof) return inst;24119 if (block.is_typeof) return inst;
2408224120
24083 switch (inst_ty.zigTypeTag()) {24121 const coerced = switch (sema.typeOf(inst).zigTypeTag()) {
24084 // TODO consider casting to c_int/f64 if they fit24122 // TODO consider casting to c_int/f64 if they fit
24085 .ComptimeInt, .ComptimeFloat => return sema.fail(block, inst_src, "integer and float literals in var args function must be casted", .{}),24123 .ComptimeInt, .ComptimeFloat => return sema.fail(
24086 else => {},24124 block,
24125 inst_src,
24126 "integer and float literals passed variadic function must be casted to a fixed-size number type",
24127 .{},
24128 ),
24129 .Fn => blk: {
24130 const fn_val = try sema.resolveConstValue(block, .unneeded, inst, undefined);
24131 const fn_decl = fn_val.pointerDecl().?;
24132 break :blk try sema.analyzeDeclRef(fn_decl);
24133 },
24134 .Array => return sema.fail(block, inst_src, "arrays must be passed by reference to variadic function", .{}),
24135 else => inst,
24136 };
24137
24138 const coerced_ty = sema.typeOf(coerced);
24139 if (!try sema.validateExternType(block, inst_src, coerced_ty, .other)) {
24140 const msg = msg: {
24141 const msg = try sema.errMsg(block, inst_src, "cannot pass '{}' to variadic function", .{coerced_ty.fmt(sema.mod)});
24142 errdefer msg.destroy(sema.gpa);
24143
24144 const src_decl = sema.mod.declPtr(block.src_decl);
24145 try sema.explainWhyTypeIsNotExtern(msg, inst_src.toSrcLoc(src_decl), coerced_ty, .other);
24146
24147 try sema.addDeclaredHereNote(msg, coerced_ty);
24148 break :msg msg;
24149 };
24150 return sema.failWithOwnedErrorMsg(msg);
24087 }24151 }
24088 // TODO implement more of this function.24152 return coerced;
24089 return inst;
24090}24153}
2409124154
24092// TODO migrate callsites to use storePtr2 instead.24155// TODO migrate callsites to use storePtr2 instead.
...@@ -27581,7 +27644,7 @@ pub fn resolveTypeLayout(...@@ -27581,7 +27644,7 @@ pub fn resolveTypeLayout(
27581 // In case of querying the ABI alignment of this optional, we will ask27644 // In case of querying the ABI alignment of this optional, we will ask
27582 // for hasRuntimeBits() of the payload type, so we need "requires comptime"27645 // for hasRuntimeBits() of the payload type, so we need "requires comptime"
27583 // to be known already before this function returns.27646 // to be known already before this function returns.
27584 _ = try sema.typeRequiresComptime(block, src, payload_ty);27647 _ = try sema.typeRequiresComptime(payload_ty);
27585 return sema.resolveTypeLayout(block, src, payload_ty);27648 return sema.resolveTypeLayout(block, src, payload_ty);
27586 },27649 },
27587 .ErrorUnion => {27650 .ErrorUnion => {
...@@ -27636,7 +27699,7 @@ fn resolveStructLayout(...@@ -27636,7 +27699,7 @@ fn resolveStructLayout(
27636 // for hasRuntimeBits() of each field, so we need "requires comptime"27699 // for hasRuntimeBits() of each field, so we need "requires comptime"
27637 // to be known already before this function returns.27700 // to be known already before this function returns.
27638 for (struct_obj.fields.values()) |field, i| {27701 for (struct_obj.fields.values()) |field, i| {
27639 _ = sema.typeRequiresComptime(block, src, field.ty) catch |err| switch (err) {27702 _ = sema.typeRequiresComptime(field.ty) catch |err| switch (err) {
27640 error.AnalysisFail => {27703 error.AnalysisFail => {
27641 const msg = sema.err orelse return err;27704 const msg = sema.err orelse return err;
27642 try sema.addFieldErrNote(block, ty, i, msg, "while checking this field", .{});27705 try sema.addFieldErrNote(block, ty, i, msg, "while checking this field", .{});
...@@ -27868,7 +27931,7 @@ fn resolveStructFully(...@@ -27868,7 +27931,7 @@ fn resolveStructFully(
27868 }27931 }
2786927932
27870 // And let's not forget comptime-only status.27933 // And let's not forget comptime-only status.
27871 _ = try sema.typeRequiresComptime(block, src, ty);27934 _ = try sema.typeRequiresComptime(ty);
27872}27935}
2787327936
27874fn resolveUnionFully(27937fn resolveUnionFully(
...@@ -27901,7 +27964,7 @@ fn resolveUnionFully(...@@ -27901,7 +27964,7 @@ fn resolveUnionFully(
27901 }27964 }
2790227965
27903 // And let's not forget comptime-only status.27966 // And let's not forget comptime-only status.
27904 _ = try sema.typeRequiresComptime(block, src, ty);27967 _ = try sema.typeRequiresComptime(ty);
27905}27968}
2790627969
27907pub fn resolveTypeFields(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!Type {27970pub fn resolveTypeFields(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!Type {
...@@ -28275,7 +28338,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void...@@ -28275,7 +28338,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
28275 };28338 };
28276 return sema.failWithOwnedErrorMsg(msg);28339 return sema.failWithOwnedErrorMsg(msg);
28277 }28340 }
28278 if (struct_obj.layout == .Extern and !sema.validateExternType(field.ty, .other)) {28341 if (struct_obj.layout == .Extern and !try sema.validateExternType(&block_scope, src, field.ty, .other)) {
28279 const msg = msg: {28342 const msg = msg: {
28280 const tree = try sema.getAstTree(&block_scope);28343 const tree = try sema.getAstTree(&block_scope);
28281 const fields_src = enumFieldSrcLoc(decl, tree.*, 0, i);28344 const fields_src = enumFieldSrcLoc(decl, tree.*, 0, i);
...@@ -28612,7 +28675,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -28612,7 +28675,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
28612 };28675 };
28613 return sema.failWithOwnedErrorMsg(msg);28676 return sema.failWithOwnedErrorMsg(msg);
28614 }28677 }
28615 if (union_obj.layout == .Extern and !sema.validateExternType(field_ty, .union_field)) {28678 if (union_obj.layout == .Extern and !try sema.validateExternType(&block_scope, src, field_ty, .union_field)) {
28616 const msg = msg: {28679 const msg = msg: {
28617 const tree = try sema.getAstTree(&block_scope);28680 const tree = try sema.getAstTree(&block_scope);
28618 const field_src = enumFieldSrcLoc(decl, tree.*, 0, field_i);28681 const field_src = enumFieldSrcLoc(decl, tree.*, 0, field_i);
...@@ -29004,7 +29067,7 @@ pub fn typeHasOnePossibleValue(...@@ -29004,7 +29067,7 @@ pub fn typeHasOnePossibleValue(
29004 },29067 },
29005 .enum_nonexhaustive => {29068 .enum_nonexhaustive => {
29006 const tag_ty = ty.castTag(.enum_nonexhaustive).?.data.tag_ty;29069 const tag_ty = ty.castTag(.enum_nonexhaustive).?.data.tag_ty;
29007 if (!(try sema.typeHasRuntimeBits(block, src, tag_ty))) {29070 if (tag_ty.zigTypeTag() != .ComptimeInt and !(try sema.typeHasRuntimeBits(block, src, tag_ty))) {
29008 return Value.zero;29071 return Value.zero;
29009 } else {29072 } else {
29010 return null;29073 return null;
...@@ -29536,7 +29599,7 @@ fn typePtrOrOptionalPtrTy(...@@ -29536,7 +29599,7 @@ fn typePtrOrOptionalPtrTy(
29536/// TODO assert the return value matches `ty.comptimeOnly`29599/// TODO assert the return value matches `ty.comptimeOnly`
29537/// TODO merge these implementations together with the "advanced"/sema_kit pattern seen29600/// TODO merge these implementations together with the "advanced"/sema_kit pattern seen
29538/// elsewhere in value.zig29601/// elsewhere in value.zig
29539pub fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!bool {29602pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
29540 return switch (ty.tag()) {29603 return switch (ty.tag()) {
29541 .u1,29604 .u1,
29542 .u8,29605 .u8,
...@@ -29627,7 +29690,7 @@ pub fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Typ...@@ -29627,7 +29690,7 @@ pub fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Typ
29627 .array,29690 .array,
29628 .array_sentinel,29691 .array_sentinel,
29629 .vector,29692 .vector,
29630 => return sema.typeRequiresComptime(block, src, ty.childType()),29693 => return sema.typeRequiresComptime(ty.childType()),
2963129694
29632 .pointer,29695 .pointer,
29633 .single_const_pointer,29696 .single_const_pointer,
...@@ -29643,7 +29706,7 @@ pub fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Typ...@@ -29643,7 +29706,7 @@ pub fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Typ
29643 if (child_ty.zigTypeTag() == .Fn) {29706 if (child_ty.zigTypeTag() == .Fn) {
29644 return child_ty.fnInfo().is_generic;29707 return child_ty.fnInfo().is_generic;
29645 } else {29708 } else {
29646 return sema.typeRequiresComptime(block, src, child_ty);29709 return sema.typeRequiresComptime(child_ty);
29647 }29710 }
29648 },29711 },
2964929712
...@@ -29652,14 +29715,14 @@ pub fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Typ...@@ -29652,14 +29715,14 @@ pub fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Typ
29652 .optional_single_const_pointer,29715 .optional_single_const_pointer,
29653 => {29716 => {
29654 var buf: Type.Payload.ElemType = undefined;29717 var buf: Type.Payload.ElemType = undefined;
29655 return sema.typeRequiresComptime(block, src, ty.optionalChild(&buf));29718 return sema.typeRequiresComptime(ty.optionalChild(&buf));
29656 },29719 },
2965729720
29658 .tuple, .anon_struct => {29721 .tuple, .anon_struct => {
29659 const tuple = ty.tupleFields();29722 const tuple = ty.tupleFields();
29660 for (tuple.types) |field_ty, i| {29723 for (tuple.types) |field_ty, i| {
29661 const have_comptime_val = tuple.values[i].tag() != .unreachable_value;29724 const have_comptime_val = tuple.values[i].tag() != .unreachable_value;
29662 if (!have_comptime_val and try sema.typeRequiresComptime(block, src, field_ty)) {29725 if (!have_comptime_val and try sema.typeRequiresComptime(field_ty)) {
29663 return true;29726 return true;
29664 }29727 }
29665 }29728 }
...@@ -29680,7 +29743,7 @@ pub fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Typ...@@ -29680,7 +29743,7 @@ pub fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Typ
29680 struct_obj.requires_comptime = .wip;29743 struct_obj.requires_comptime = .wip;
29681 for (struct_obj.fields.values()) |field| {29744 for (struct_obj.fields.values()) |field| {
29682 if (field.is_comptime) continue;29745 if (field.is_comptime) continue;
29683 if (try sema.typeRequiresComptime(block, src, field.ty)) {29746 if (try sema.typeRequiresComptime(field.ty)) {
29684 struct_obj.requires_comptime = .yes;29747 struct_obj.requires_comptime = .yes;
29685 return true;29748 return true;
29686 }29749 }
...@@ -29704,7 +29767,7 @@ pub fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Typ...@@ -29704,7 +29767,7 @@ pub fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Typ
2970429767
29705 union_obj.requires_comptime = .wip;29768 union_obj.requires_comptime = .wip;
29706 for (union_obj.fields.values()) |field| {29769 for (union_obj.fields.values()) |field| {
29707 if (try sema.typeRequiresComptime(block, src, field.ty)) {29770 if (try sema.typeRequiresComptime(field.ty)) {
29708 union_obj.requires_comptime = .yes;29771 union_obj.requires_comptime = .yes;
29709 return true;29772 return true;
29710 }29773 }
...@@ -29715,18 +29778,18 @@ pub fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Typ...@@ -29715,18 +29778,18 @@ pub fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Typ
29715 }29778 }
29716 },29779 },
2971729780
29718 .error_union => return sema.typeRequiresComptime(block, src, ty.errorUnionPayload()),29781 .error_union => return sema.typeRequiresComptime(ty.errorUnionPayload()),
29719 .anyframe_T => {29782 .anyframe_T => {
29720 const child_ty = ty.castTag(.anyframe_T).?.data;29783 const child_ty = ty.castTag(.anyframe_T).?.data;
29721 return sema.typeRequiresComptime(block, src, child_ty);29784 return sema.typeRequiresComptime(child_ty);
29722 },29785 },
29723 .enum_numbered => {29786 .enum_numbered => {
29724 const tag_ty = ty.castTag(.enum_numbered).?.data.tag_ty;29787 const tag_ty = ty.castTag(.enum_numbered).?.data.tag_ty;
29725 return sema.typeRequiresComptime(block, src, tag_ty);29788 return sema.typeRequiresComptime(tag_ty);
29726 },29789 },
29727 .enum_full, .enum_nonexhaustive => {29790 .enum_full, .enum_nonexhaustive => {
29728 const tag_ty = ty.cast(Type.Payload.EnumFull).?.data.tag_ty;29791 const tag_ty = ty.cast(Type.Payload.EnumFull).?.data.tag_ty;
29729 return sema.typeRequiresComptime(block, src, tag_ty);29792 return sema.typeRequiresComptime(tag_ty);
29730 },29793 },
29731 };29794 };
29732}29795}
...@@ -29764,7 +29827,7 @@ fn unionFieldAlignment(...@@ -29764,7 +29827,7 @@ fn unionFieldAlignment(
29764}29827}
2976529828
29766/// Synchronize logic with `Type.isFnOrHasRuntimeBits`.29829/// Synchronize logic with `Type.isFnOrHasRuntimeBits`.
29767pub fn fnHasRuntimeBits(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!bool {29830pub fn fnHasRuntimeBits(sema: *Sema, ty: Type) CompileError!bool {
29768 const fn_info = ty.fnInfo();29831 const fn_info = ty.fnInfo();
29769 if (fn_info.is_generic) return false;29832 if (fn_info.is_generic) return false;
29770 if (fn_info.is_var_args) return true;29833 if (fn_info.is_var_args) return true;
...@@ -29773,7 +29836,7 @@ pub fn fnHasRuntimeBits(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) C...@@ -29773,7 +29836,7 @@ pub fn fnHasRuntimeBits(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) C
29773 .Inline => return false,29836 .Inline => return false,
29774 else => {},29837 else => {},
29775 }29838 }
29776 if (try sema.typeRequiresComptime(block, src, fn_info.return_type)) {29839 if (try sema.typeRequiresComptime(fn_info.return_type)) {
29777 return false;29840 return false;
29778 }29841 }
29779 return true;29842 return true;
src/arch/wasm/abi.zig+8
...@@ -23,6 +23,10 @@ pub fn classifyType(ty: Type, target: Target) [2]Class {...@@ -23,6 +23,10 @@ pub fn classifyType(ty: Type, target: Target) [2]Class {
23 if (!ty.hasRuntimeBitsIgnoreComptime()) return none;23 if (!ty.hasRuntimeBitsIgnoreComptime()) return none;
24 switch (ty.zigTypeTag()) {24 switch (ty.zigTypeTag()) {
25 .Struct => {25 .Struct => {
26 if (ty.containerLayout() == .Packed) {
27 if (ty.bitSize(target) <= 64) return direct;
28 return .{ .direct, .direct };
29 }
26 // When the struct type is non-scalar30 // When the struct type is non-scalar
27 if (ty.structFieldCount() > 1) return memory;31 if (ty.structFieldCount() > 1) return memory;
28 // When the struct's alignment is non-natural32 // When the struct's alignment is non-natural
...@@ -57,6 +61,10 @@ pub fn classifyType(ty: Type, target: Target) [2]Class {...@@ -57,6 +61,10 @@ pub fn classifyType(ty: Type, target: Target) [2]Class {
57 return direct;61 return direct;
58 },62 },
59 .Union => {63 .Union => {
64 if (ty.containerLayout() == .Packed) {
65 if (ty.bitSize(target) <= 64) return direct;
66 return .{ .direct, .direct };
67 }
60 const layout = ty.unionGetLayout(target);68 const layout = ty.unionGetLayout(target);
61 std.debug.assert(layout.tag_size == 0);69 std.debug.assert(layout.tag_size == 0);
62 if (ty.unionFields().count() > 1) return memory;70 if (ty.unionFields().count() > 1) return memory;
src/arch/x86_64/abi.zig+22-2
...@@ -5,7 +5,7 @@ const assert = std.debug.assert;...@@ -5,7 +5,7 @@ const assert = std.debug.assert;
5const Register = @import("bits.zig").Register;5const Register = @import("bits.zig").Register;
6const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;6const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;
77
8pub const Class = enum { integer, sse, sseup, x87, x87up, complex_x87, memory, none };8pub const Class = enum { integer, sse, sseup, x87, x87up, complex_x87, memory, none, win_i128 };
99
10pub fn classifyWindows(ty: Type, target: Target) Class {10pub fn classifyWindows(ty: Type, target: Target) Class {
11 // https://docs.microsoft.com/en-gb/cpp/build/x64-calling-convention?view=vs-201711 // https://docs.microsoft.com/en-gb/cpp/build/x64-calling-convention?view=vs-2017
...@@ -34,7 +34,15 @@ pub fn classifyWindows(ty: Type, target: Target) Class {...@@ -34,7 +34,15 @@ pub fn classifyWindows(ty: Type, target: Target) Class {
34 => switch (ty.abiSize(target)) {34 => switch (ty.abiSize(target)) {
35 0 => unreachable,35 0 => unreachable,
36 1, 2, 4, 8 => return .integer,36 1, 2, 4, 8 => return .integer,
37 else => return .memory,37 else => switch (ty.zigTypeTag()) {
38 .Int => return .win_i128,
39 .Struct, .Union => if (ty.containerLayout() == .Packed) {
40 return .win_i128;
41 } else {
42 return .memory;
43 },
44 else => return .memory,
45 },
38 },46 },
3947
40 .Float, .Vector => return .sse,48 .Float, .Vector => return .sse,
...@@ -174,6 +182,12 @@ pub fn classifySystemV(ty: Type, target: Target) [8]Class {...@@ -174,6 +182,12 @@ pub fn classifySystemV(ty: Type, target: Target) [8]Class {
174 // "If the size of the aggregate exceeds a single eightbyte, each is classified182 // "If the size of the aggregate exceeds a single eightbyte, each is classified
175 // separately.".183 // separately.".
176 const ty_size = ty.abiSize(target);184 const ty_size = ty.abiSize(target);
185 if (ty.containerLayout() == .Packed) {
186 assert(ty_size <= 128);
187 result[0] = .integer;
188 if (ty_size > 64) result[1] = .integer;
189 return result;
190 }
177 if (ty_size > 64)191 if (ty_size > 64)
178 return memory_class;192 return memory_class;
179193
...@@ -284,6 +298,12 @@ pub fn classifySystemV(ty: Type, target: Target) [8]Class {...@@ -284,6 +298,12 @@ pub fn classifySystemV(ty: Type, target: Target) [8]Class {
284 // "If the size of the aggregate exceeds a single eightbyte, each is classified298 // "If the size of the aggregate exceeds a single eightbyte, each is classified
285 // separately.".299 // separately.".
286 const ty_size = ty.abiSize(target);300 const ty_size = ty.abiSize(target);
301 if (ty.containerLayout() == .Packed) {
302 assert(ty_size <= 128);
303 result[0] = .integer;
304 if (ty_size > 64) result[1] = .integer;
305 return result;
306 }
287 if (ty_size > 64)307 if (ty_size > 64)
288 return memory_class;308 return memory_class;
289309
src/codegen/llvm.zig+35-39
...@@ -9051,7 +9051,7 @@ pub const FuncGen = struct {...@@ -9051,7 +9051,7 @@ pub const FuncGen = struct {
9051 }9051 }
9052 },9052 },
9053 },9053 },
9054 .Union => return self.unionFieldPtr(inst, struct_ptr, struct_ty, field_index),9054 .Union => return self.unionFieldPtr(inst, struct_ptr, struct_ty),
9055 else => unreachable,9055 else => unreachable,
9056 }9056 }
9057 }9057 }
...@@ -9061,16 +9061,13 @@ pub const FuncGen = struct {...@@ -9061,16 +9061,13 @@ pub const FuncGen = struct {
9061 inst: Air.Inst.Index,9061 inst: Air.Inst.Index,
9062 union_ptr: *const llvm.Value,9062 union_ptr: *const llvm.Value,
9063 union_ty: Type,9063 union_ty: Type,
9064 field_index: c_uint,
9065 ) !?*const llvm.Value {9064 ) !?*const llvm.Value {
9066 const union_obj = union_ty.cast(Type.Payload.Union).?.data;
9067 const field = &union_obj.fields.values()[field_index];
9068 const result_llvm_ty = try self.dg.lowerType(self.air.typeOfIndex(inst));9065 const result_llvm_ty = try self.dg.lowerType(self.air.typeOfIndex(inst));
9069 if (!field.ty.hasRuntimeBitsIgnoreComptime()) {
9070 return null;
9071 }
9072 const target = self.dg.module.getTarget();9066 const target = self.dg.module.getTarget();
9073 const layout = union_ty.unionGetLayout(target);9067 const layout = union_ty.unionGetLayout(target);
9068 if (layout.payload_size == 0) {
9069 return self.builder.buildBitCast(union_ptr, result_llvm_ty, "");
9070 }
9074 const payload_index = @boolToInt(layout.tag_align >= layout.payload_align);9071 const payload_index = @boolToInt(layout.tag_align >= layout.payload_align);
9075 const union_field_ptr = self.builder.buildStructGEP(union_ptr, payload_index, "");9072 const union_field_ptr = self.builder.buildStructGEP(union_ptr, payload_index, "");
9076 return self.builder.buildBitCast(union_field_ptr, result_llvm_ty, "");9073 return self.builder.buildBitCast(union_field_ptr, result_llvm_ty, "");
...@@ -9677,22 +9674,7 @@ fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*const llvm....@@ -9677,22 +9674,7 @@ fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*const llvm.
9677 }9674 }
9678 },9675 },
9679 .C => {9676 .C => {
9680 const is_scalar = switch (fn_info.return_type.zigTypeTag()) {9677 const is_scalar = isScalar(fn_info.return_type);
9681 .Void,
9682 .Bool,
9683 .NoReturn,
9684 .Int,
9685 .Float,
9686 .Pointer,
9687 .Optional,
9688 .ErrorSet,
9689 .Enum,
9690 .AnyFrame,
9691 .Vector,
9692 => true,
9693
9694 else => false,
9695 };
9696 switch (target.cpu.arch) {9678 switch (target.cpu.arch) {
9697 .mips, .mipsel => return dg.lowerType(fn_info.return_type),9679 .mips, .mipsel => return dg.lowerType(fn_info.return_type),
9698 .x86_64 => switch (target.os.tag) {9680 .x86_64 => switch (target.os.tag) {
...@@ -9705,6 +9687,7 @@ fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*const llvm....@@ -9705,6 +9687,7 @@ fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*const llvm.
9705 return dg.context.intType(@intCast(c_uint, abi_size * 8));9687 return dg.context.intType(@intCast(c_uint, abi_size * 8));
9706 }9688 }
9707 },9689 },
9690 .win_i128 => return dg.context.intType(64).vectorType(2),
9708 .memory => return dg.context.voidType(),9691 .memory => return dg.context.voidType(),
9709 .sse => return dg.lowerType(fn_info.return_type),9692 .sse => return dg.lowerType(fn_info.return_type),
9710 else => unreachable,9693 else => unreachable,
...@@ -9745,6 +9728,7 @@ fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*const llvm....@@ -9745,6 +9728,7 @@ fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*const llvm.
9745 @panic("TODO");9728 @panic("TODO");
9746 },9729 },
9747 .memory => unreachable, // handled above9730 .memory => unreachable, // handled above
9731 .win_i128 => unreachable, // windows only
9748 .none => break,9732 .none => break,
9749 }9733 }
9750 }9734 }
...@@ -9840,22 +9824,7 @@ const ParamTypeIterator = struct {...@@ -9840,22 +9824,7 @@ const ParamTypeIterator = struct {
9840 @panic("TODO implement async function lowering in the LLVM backend");9824 @panic("TODO implement async function lowering in the LLVM backend");
9841 },9825 },
9842 .C => {9826 .C => {
9843 const is_scalar = switch (ty.zigTypeTag()) {9827 const is_scalar = isScalar(ty);
9844 .Void,
9845 .Bool,
9846 .NoReturn,
9847 .Int,
9848 .Float,
9849 .Pointer,
9850 .Optional,
9851 .ErrorSet,
9852 .Enum,
9853 .AnyFrame,
9854 .Vector,
9855 => true,
9856
9857 else => false,
9858 };
9859 switch (it.target.cpu.arch) {9828 switch (it.target.cpu.arch) {
9860 .riscv32, .riscv64 => {9829 .riscv32, .riscv64 => {
9861 it.zig_index += 1;9830 it.zig_index += 1;
...@@ -9884,6 +9853,11 @@ const ParamTypeIterator = struct {...@@ -9884,6 +9853,11 @@ const ParamTypeIterator = struct {
9884 return .abi_sized_int;9853 return .abi_sized_int;
9885 }9854 }
9886 },9855 },
9856 .win_i128 => {
9857 it.zig_index += 1;
9858 it.llvm_index += 1;
9859 return .byref;
9860 },
9887 .memory => {9861 .memory => {
9888 it.zig_index += 1;9862 it.zig_index += 1;
9889 it.llvm_index += 1;9863 it.llvm_index += 1;
...@@ -9938,6 +9912,7 @@ const ParamTypeIterator = struct {...@@ -9938,6 +9912,7 @@ const ParamTypeIterator = struct {
9938 @panic("TODO");9912 @panic("TODO");
9939 },9913 },
9940 .memory => unreachable, // handled above9914 .memory => unreachable, // handled above
9915 .win_i128 => unreachable, // windows only
9941 .none => break,9916 .none => break,
9942 }9917 }
9943 }9918 }
...@@ -10109,6 +10084,27 @@ fn isByRef(ty: Type) bool {...@@ -10109,6 +10084,27 @@ fn isByRef(ty: Type) bool {
10109 }10084 }
10110}10085}
1011110086
10087fn isScalar(ty: Type) bool {
10088 return switch (ty.zigTypeTag()) {
10089 .Void,
10090 .Bool,
10091 .NoReturn,
10092 .Int,
10093 .Float,
10094 .Pointer,
10095 .Optional,
10096 .ErrorSet,
10097 .Enum,
10098 .AnyFrame,
10099 .Vector,
10100 => true,
10101
10102 .Struct => ty.containerLayout() == .Packed,
10103 .Union => ty.containerLayout() == .Packed,
10104 else => false,
10105 };
10106}
10107
10112/// This function returns true if we expect LLVM to lower x86_fp80 correctly10108/// This function returns true if we expect LLVM to lower x86_fp80 correctly
10113/// and false if we expect LLVM to crash if it counters an x86_fp80 type.10109/// and false if we expect LLVM to crash if it counters an x86_fp80 type.
10114fn backendSupportsF80(target: std.Target) bool {10110fn backendSupportsF80(target: std.Target) bool {
src/translate_c.zig+4
...@@ -1166,6 +1166,10 @@ fn transRecordDecl(c: *Context, scope: *Scope, record_decl: *const clang.RecordD...@@ -1166,6 +1166,10 @@ fn transRecordDecl(c: *Context, scope: *Scope, record_decl: *const clang.RecordD
1166 });1166 });
1167 }1167 }
11681168
1169 if (!c.zig_is_stage1 and is_packed) {
1170 return failDecl(c, record_loc, bare_name, "cannot translate packed record union", .{});
1171 }
1172
1169 const record_payload = try c.arena.create(ast.Payload.Record);1173 const record_payload = try c.arena.create(ast.Payload.Record);
1170 record_payload.* = .{1174 record_payload.* = .{
1171 .base = .{ .tag = ([2]Tag{ .@"struct", .@"union" })[@boolToInt(is_union)] },1175 .base = .{ .tag = ([2]Tag{ .@"struct", .@"union" })[@boolToInt(is_union)] },
src/type.zig+5-2
...@@ -2042,6 +2042,9 @@ pub const Type = extern union {...@@ -2042,6 +2042,9 @@ pub const Type = extern union {
2042 try writer.writeAll("fn(");2042 try writer.writeAll("fn(");
2043 for (fn_info.param_types) |param_ty, i| {2043 for (fn_info.param_types) |param_ty, i| {
2044 if (i != 0) try writer.writeAll(", ");2044 if (i != 0) try writer.writeAll(", ");
2045 if (std.math.cast(u5, i)) |index| if (@truncate(u1, fn_info.noalias_bits >> index) != 0) {
2046 try writer.writeAll("noalias ");
2047 };
2045 if (param_ty.tag() == .generic_poison) {2048 if (param_ty.tag() == .generic_poison) {
2046 try writer.writeAll("anytype");2049 try writer.writeAll("anytype");
2047 } else {2050 } else {
...@@ -2398,7 +2401,7 @@ pub const Type = extern union {...@@ -2398,7 +2401,7 @@ pub const Type = extern union {
2398 } else if (ty.childType().zigTypeTag() == .Fn) {2401 } else if (ty.childType().zigTypeTag() == .Fn) {
2399 return !ty.childType().fnInfo().is_generic;2402 return !ty.childType().fnInfo().is_generic;
2400 } else if (sema_kit) |sk| {2403 } else if (sema_kit) |sk| {
2401 return !(try sk.sema.typeRequiresComptime(sk.block, sk.src, ty));2404 return !(try sk.sema.typeRequiresComptime(ty));
2402 } else {2405 } else {
2403 return !comptimeOnly(ty);2406 return !comptimeOnly(ty);
2404 }2407 }
...@@ -2437,7 +2440,7 @@ pub const Type = extern union {...@@ -2437,7 +2440,7 @@ pub const Type = extern union {
2437 if (ignore_comptime_only) {2440 if (ignore_comptime_only) {
2438 return true;2441 return true;
2439 } else if (sema_kit) |sk| {2442 } else if (sema_kit) |sk| {
2440 return !(try sk.sema.typeRequiresComptime(sk.block, sk.src, child_ty));2443 return !(try sk.sema.typeRequiresComptime(child_ty));
2441 } else {2444 } else {
2442 return !comptimeOnly(child_ty);2445 return !comptimeOnly(child_ty);
2443 }2446 }
src/value.zig+26-3
...@@ -2940,17 +2940,24 @@ pub const Value = extern union {...@@ -2940,17 +2940,24 @@ pub const Value = extern union {
2940 }2940 }
29412941
2942 pub fn intToFloat(val: Value, arena: Allocator, int_ty: Type, float_ty: Type, target: Target) !Value {2942 pub fn intToFloat(val: Value, arena: Allocator, int_ty: Type, float_ty: Type, target: Target) !Value {
2943 return intToFloatAdvanced(val, arena, int_ty, float_ty, target, null) catch |err| switch (err) {
2944 error.OutOfMemory => return error.OutOfMemory,
2945 else => unreachable,
2946 };
2947 }
2948
2949 pub fn intToFloatAdvanced(val: Value, arena: Allocator, int_ty: Type, float_ty: Type, target: Target, sema_kit: ?Module.WipAnalysis) !Value {
2943 if (int_ty.zigTypeTag() == .Vector) {2950 if (int_ty.zigTypeTag() == .Vector) {
2944 const result_data = try arena.alloc(Value, int_ty.vectorLen());2951 const result_data = try arena.alloc(Value, int_ty.vectorLen());
2945 for (result_data) |*scalar, i| {2952 for (result_data) |*scalar, i| {
2946 scalar.* = try intToFloatScalar(val.indexVectorlike(i), arena, float_ty.scalarType(), target);2953 scalar.* = try intToFloatScalar(val.indexVectorlike(i), arena, float_ty.scalarType(), target, sema_kit);
2947 }2954 }
2948 return Value.Tag.aggregate.create(arena, result_data);2955 return Value.Tag.aggregate.create(arena, result_data);
2949 }2956 }
2950 return intToFloatScalar(val, arena, float_ty, target);2957 return intToFloatScalar(val, arena, float_ty, target, sema_kit);
2951 }2958 }
29522959
2953 pub fn intToFloatScalar(val: Value, arena: Allocator, float_ty: Type, target: Target) !Value {2960 pub fn intToFloatScalar(val: Value, arena: Allocator, float_ty: Type, target: Target, sema_kit: ?Module.WipAnalysis) !Value {
2954 switch (val.tag()) {2961 switch (val.tag()) {
2955 .undef, .zero, .one => return val,2962 .undef, .zero, .one => return val,
2956 .the_only_possible_value => return Value.initTag(.zero), // for i0, u02963 .the_only_possible_value => return Value.initTag(.zero), // for i0, u0
...@@ -2970,6 +2977,22 @@ pub const Value = extern union {...@@ -2970,6 +2977,22 @@ pub const Value = extern union {
2970 const float = bigIntToFloat(limbs, false);2977 const float = bigIntToFloat(limbs, false);
2971 return floatToValue(float, arena, float_ty, target);2978 return floatToValue(float, arena, float_ty, target);
2972 },2979 },
2980 .lazy_align => {
2981 const ty = val.castTag(.lazy_align).?.data;
2982 if (sema_kit) |sk| {
2983 return intToFloatInner((try ty.abiAlignmentAdvanced(target, .{ .sema_kit = sk })).scalar, arena, float_ty, target);
2984 } else {
2985 return intToFloatInner(ty.abiAlignment(target), arena, float_ty, target);
2986 }
2987 },
2988 .lazy_size => {
2989 const ty = val.castTag(.lazy_size).?.data;
2990 if (sema_kit) |sk| {
2991 return intToFloatInner((try ty.abiSizeAdvanced(target, .{ .sema_kit = sk })).scalar, arena, float_ty, target);
2992 } else {
2993 return intToFloatInner(ty.abiSize(target), arena, float_ty, target);
2994 }
2995 },
2973 else => unreachable,2996 else => unreachable,
2974 }2997 }
2975 }2998 }
test/behavior/enum.zig+7
...@@ -1175,3 +1175,10 @@ test "Non-exhaustive enum with nonstandard int size behaves correctly" {...@@ -1175,3 +1175,10 @@ test "Non-exhaustive enum with nonstandard int size behaves correctly" {
1175 const E = enum(u15) { _ };1175 const E = enum(u15) { _ };
1176 try expect(@sizeOf(E) == @sizeOf(u15));1176 try expect(@sizeOf(E) == @sizeOf(u15));
1177}1177}
1178
1179test "Non-exhaustive enum backed by comptime_int" {
1180 const E = enum(comptime_int) { a, b, c, _ };
1181 comptime var e: E = .a;
1182 e = @intToEnum(E, 378089457309184723749);
1183 try expect(@enumToInt(e) == 378089457309184723749);
1184}
test/behavior/packed-struct.zig+26
...@@ -579,3 +579,29 @@ test "runtime init of unnamed packed struct type" {...@@ -579,3 +579,29 @@ test "runtime init of unnamed packed struct type" {
579 }579 }
580 }{ .x = z }).m();580 }{ .x = z }).m();
581}581}
582
583test "packed struct passed to callconv(.C) function" {
584 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
585 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
586 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
587 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
588
589 const S = struct {
590 const Packed = packed struct {
591 a: u16,
592 b: bool = true,
593 c: bool = true,
594 d: u46 = 0,
595 };
596
597 fn foo(p: Packed, a1: u64, a2: u64, a3: u64, a4: u64, a5: u64) callconv(.C) bool {
598 return p.a == 12345 and p.b == true and p.c == true and p.d == 0 and a1 == 5 and a2 == 4 and a3 == 3 and a4 == 2 and a5 == 1;
599 }
600 };
601 const result = S.foo(S.Packed{
602 .a = 12345,
603 .b = true,
604 .c = true,
605 }, 5, 4, 3, 2, 1);
606 try expect(result);
607}
test/behavior/sizeof_and_typeof.zig+11
...@@ -301,3 +301,14 @@ test "array access of generic param in typeof expression" {...@@ -301,3 +301,14 @@ test "array access of generic param in typeof expression" {
301 try expect(S.first("a") == 'a');301 try expect(S.first("a") == 'a');
302 comptime try expect(S.first("a") == 'a');302 comptime try expect(S.first("a") == 'a');
303}303}
304
305test "lazy size cast to float" {
306 {
307 const S = struct { a: u8 };
308 try expect(@intToFloat(f32, @sizeOf(S)) == 1.0);
309 }
310 {
311 const S = struct { a: u8 };
312 try expect(@as(f32, @sizeOf(S)) == 1.0);
313 }
314}
test/behavior/union.zig+29-1
...@@ -690,7 +690,7 @@ test "union with only 1 field casted to its enum type which has enum value speci...@@ -690,7 +690,7 @@ test "union with only 1 field casted to its enum type which has enum value speci
690690
691 var e = Expr{ .Literal = Literal{ .Bool = true } };691 var e = Expr{ .Literal = Literal{ .Bool = true } };
692 comptime try expect(Tag(ExprTag) == comptime_int);692 comptime try expect(Tag(ExprTag) == comptime_int);
693 var t = @as(ExprTag, e);693 comptime var t = @as(ExprTag, e);
694 try expect(t == Expr.Literal);694 try expect(t == Expr.Literal);
695 try expect(@enumToInt(t) == 33);695 try expect(@enumToInt(t) == 33);
696 comptime try expect(@enumToInt(t) == 33);696 comptime try expect(@enumToInt(t) == 33);
...@@ -1352,3 +1352,31 @@ test "@unionInit uses tag value instead of field index" {...@@ -1352,3 +1352,31 @@ test "@unionInit uses tag value instead of field index" {
1352 }1352 }
1353 try expect(@enumToInt(u) == 255);1353 try expect(@enumToInt(u) == 255);
1354}1354}
1355
1356test "union field ptr - zero sized payload" {
1357 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1358 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1359 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1360
1361 const U = union {
1362 foo: void,
1363 bar: void,
1364 fn bar(_: *void) void {}
1365 };
1366 var u: U = .{ .foo = {} };
1367 U.bar(&u.foo);
1368}
1369
1370test "union field ptr - zero sized field" {
1371 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1372 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1373 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1374
1375 const U = union {
1376 foo: void,
1377 bar: u32,
1378 fn bar(_: *void) void {}
1379 };
1380 var u: U = .{ .foo = {} };
1381 U.bar(&u.foo);
1382}
test/c_abi/cfuncs.c+29-49
...@@ -86,24 +86,8 @@ struct MedStructMixed {...@@ -86,24 +86,8 @@ struct MedStructMixed {
86void zig_med_struct_mixed(struct MedStructMixed);86void zig_med_struct_mixed(struct MedStructMixed);
87struct MedStructMixed zig_ret_med_struct_mixed();87struct MedStructMixed zig_ret_med_struct_mixed();
8888
89struct SmallPackedStruct {89void zig_small_packed_struct(uint8_t);
90 uint8_t a: 2;90void zig_big_packed_struct(__int128);
91 uint8_t b: 2;
92 uint8_t c: 2;
93 uint8_t d: 2;
94 uint8_t e: 1;
95};
96
97struct BigPackedStruct {
98 uint64_t a: 64;
99 uint64_t b: 64;
100 uint64_t c: 64;
101 uint64_t d: 64;
102 uint8_t e: 8;
103};
104
105//void zig_small_packed_struct(struct SmallPackedStruct); // #1481
106void zig_big_packed_struct(struct BigPackedStruct);
10791
108struct SplitStructInts {92struct SplitStructInts {
109 uint64_t a;93 uint64_t a;
...@@ -176,13 +160,19 @@ void run_c_tests(void) {...@@ -176,13 +160,19 @@ void run_c_tests(void) {
176 }160 }
177161
178 {162 {
179 struct BigPackedStruct s = {1, 2, 3, 4, 5};163 __int128 s = 0;
164 s |= 1 << 0;
165 s |= (__int128)2 << 64;
180 zig_big_packed_struct(s);166 zig_big_packed_struct(s);
181 }167 }
182168
183 {169 {
184 struct SmallPackedStruct s = {0, 1, 2, 3, 1};170 uint8_t s = 0;
185 //zig_small_packed_struct(s);171 s |= 0 << 0;
172 s |= 1 << 2;
173 s |= 2 << 4;
174 s |= 3 << 6;
175 zig_small_packed_struct(s);
186 }176 }
187177
188 {178 {
...@@ -378,42 +368,32 @@ void c_split_struct_mixed(struct SplitStructMixed x) {...@@ -378,42 +368,32 @@ void c_split_struct_mixed(struct SplitStructMixed x) {
378 assert_or_panic(y.c == 1337.0f);368 assert_or_panic(y.c == 1337.0f);
379}369}
380370
381struct SmallPackedStruct c_ret_small_packed_struct() {371uint8_t c_ret_small_packed_struct() {
382 struct SmallPackedStruct s = {372 uint8_t s = 0;
383 .a = 0,373 s |= 0 << 0;
384 .b = 1,374 s |= 1 << 2;
385 .c = 2,375 s |= 2 << 4;
386 .d = 3,376 s |= 3 << 6;
387 .e = 1,
388 };
389 return s;377 return s;
390}378}
391379
392void c_small_packed_struct(struct SmallPackedStruct x) {380void c_small_packed_struct(uint8_t x) {
393 assert_or_panic(x.a == 0);381 assert_or_panic(((x >> 0) & 0x3) == 0);
394 assert_or_panic(x.a == 1);382 assert_or_panic(((x >> 2) & 0x3) == 1);
395 assert_or_panic(x.a == 2);383 assert_or_panic(((x >> 4) & 0x3) == 2);
396 assert_or_panic(x.a == 3);384 assert_or_panic(((x >> 6) & 0x3) == 3);
397 assert_or_panic(x.e == 1);
398}385}
399386
400struct BigPackedStruct c_ret_big_packed_struct() {387__int128 c_ret_big_packed_struct() {
401 struct BigPackedStruct s = {388 __int128 s = 0;
402 .a = 1,389 s |= 1 << 0;
403 .b = 2,390 s |= (__int128)2 << 64;
404 .c = 3,
405 .d = 4,
406 .e = 5,
407 };
408 return s;391 return s;
409}392}
410393
411void c_big_packed_struct(struct BigPackedStruct x) {394void c_big_packed_struct(__int128 x) {
412 assert_or_panic(x.a == 1);395 assert_or_panic(((x >> 0) & 0xFFFFFFFFFFFFFFFF) == 1);
413 assert_or_panic(x.b == 2);396 assert_or_panic(((x >> 64) & 0xFFFFFFFFFFFFFFFF) == 2);
414 assert_or_panic(x.c == 3);
415 assert_or_panic(x.d == 4);
416 assert_or_panic(x.e == 5);
417}397}
418398
419struct SplitStructMixed c_ret_split_struct_mixed() {399struct SplitStructMixed c_ret_split_struct_mixed() {
test/c_abi/main.zig+10-23
...@@ -263,37 +263,30 @@ const SmallPackedStruct = packed struct {...@@ -263,37 +263,30 @@ const SmallPackedStruct = packed struct {
263 b: u2,263 b: u2,
264 c: u2,264 c: u2,
265 d: u2,265 d: u2,
266 e: bool,
267};266};
268const c_small_packed_struct: fn (SmallPackedStruct) callconv(.C) void = @compileError("TODO: #1481");267extern fn c_small_packed_struct(SmallPackedStruct) void;
269extern fn c_ret_small_packed_struct() SmallPackedStruct;268extern fn c_ret_small_packed_struct() SmallPackedStruct;
270269
271// waiting on #1481270export fn zig_small_packed_struct(x: SmallPackedStruct) void {
272//export fn zig_small_packed_struct(x: SmallPackedStruct) void {271 expect(x.a == 0) catch @panic("test failure");
273// expect(x.a == 0) catch @panic("test failure");272 expect(x.b == 1) catch @panic("test failure");
274// expect(x.b == 1) catch @panic("test failure");273 expect(x.c == 2) catch @panic("test failure");
275// expect(x.c == 2) catch @panic("test failure");274 expect(x.d == 3) catch @panic("test failure");
276// expect(x.d == 3) catch @panic("test failure");275}
277// expect(x.e) catch @panic("test failure");
278//}
279276
280test "C ABI small packed struct" {277test "C ABI small packed struct" {
281 var s = SmallPackedStruct{ .a = 0, .b = 1, .c = 2, .d = 3, .e = true };278 var s = SmallPackedStruct{ .a = 0, .b = 1, .c = 2, .d = 3 };
282 _ = s; //c_small_packed_struct(s); // waiting on #1481279 c_small_packed_struct(s);
283 var s2 = c_ret_small_packed_struct();280 var s2 = c_ret_small_packed_struct();
284 try expect(s2.a == 0);281 try expect(s2.a == 0);
285 try expect(s2.b == 1);282 try expect(s2.b == 1);
286 try expect(s2.c == 2);283 try expect(s2.c == 2);
287 try expect(s2.d == 3);284 try expect(s2.d == 3);
288 try expect(s2.e);
289}285}
290286
291const BigPackedStruct = packed struct {287const BigPackedStruct = packed struct {
292 a: u64,288 a: u64,
293 b: u64,289 b: u64,
294 c: u64,
295 d: u64,
296 e: u8,
297};290};
298extern fn c_big_packed_struct(BigPackedStruct) void;291extern fn c_big_packed_struct(BigPackedStruct) void;
299extern fn c_ret_big_packed_struct() BigPackedStruct;292extern fn c_ret_big_packed_struct() BigPackedStruct;
...@@ -301,20 +294,14 @@ extern fn c_ret_big_packed_struct() BigPackedStruct;...@@ -301,20 +294,14 @@ extern fn c_ret_big_packed_struct() BigPackedStruct;
301export fn zig_big_packed_struct(x: BigPackedStruct) void {294export fn zig_big_packed_struct(x: BigPackedStruct) void {
302 expect(x.a == 1) catch @panic("test failure");295 expect(x.a == 1) catch @panic("test failure");
303 expect(x.b == 2) catch @panic("test failure");296 expect(x.b == 2) catch @panic("test failure");
304 expect(x.c == 3) catch @panic("test failure");
305 expect(x.d == 4) catch @panic("test failure");
306 expect(x.e == 5) catch @panic("test failure");
307}297}
308298
309test "C ABI big packed struct" {299test "C ABI big packed struct" {
310 var s = BigPackedStruct{ .a = 1, .b = 2, .c = 3, .d = 4, .e = 5 };300 var s = BigPackedStruct{ .a = 1, .b = 2 };
311 c_big_packed_struct(s);301 c_big_packed_struct(s);
312 var s2 = c_ret_big_packed_struct();302 var s2 = c_ret_big_packed_struct();
313 try expect(s2.a == 1);303 try expect(s2.a == 1);
314 try expect(s2.b == 2);304 try expect(s2.b == 2);
315 try expect(s2.c == 3);
316 try expect(s2.d == 4);
317 try expect(s2.e == 5);
318}305}
319306
320const SplitStructInt = extern struct {307const SplitStructInt = extern struct {
test/cases/compile_errors/C_pointer_pointing_to_non_C_ABI_compatible_type_or_has_align_attr.zig+1-1
...@@ -10,5 +10,5 @@ export fn a() void {...@@ -10,5 +10,5 @@ export fn a() void {
10// target=native10// target=native
11//11//
12// :3:19: error: C pointers cannot point to non-C-ABI-compatible type 'tmp.Foo'12// :3:19: error: C pointers cannot point to non-C-ABI-compatible type 'tmp.Foo'
13// :3:19: note: only structs with packed or extern layout are extern compatible13// :3:19: note: only extern structs and ABI sized packed structs are extern compatible
14// :1:13: note: struct declared here14// :1:13: note: struct declared here
test/cases/compile_errors/enum_backed_by_comptime_int_must_be_comptime.zig created+11
...@@ -0,0 +1,11 @@
1pub export fn entry() void {
2 const E = enum(comptime_int) { a, b, c, _ };
3 var e: E = .a;
4 _ = e;
5}
6
7// error
8// backend=stage2
9// target=native
10//
11// :3:12: error: variable of type 'tmp.entry.E' must be const or comptime
test/cases/compile_errors/function_with_non-extern_non-packed_struct_parameter.zig+1-1
...@@ -10,5 +10,5 @@ export fn entry(foo: Foo) void { _ = foo; }...@@ -10,5 +10,5 @@ export fn entry(foo: Foo) void { _ = foo; }
10// target=native10// target=native
11//11//
12// :6:17: error: parameter of type 'tmp.Foo' not allowed in function with calling convention 'C'12// :6:17: error: parameter of type 'tmp.Foo' not allowed in function with calling convention 'C'
13// :6:17: note: only structs with packed or extern layout are extern compatible13// :6:17: note: only extern structs and ABI sized packed structs are extern compatible
14// :1:13: note: struct declared here14// :1:13: note: struct declared here
test/cases/compile_errors/function_with_non-extern_non-packed_union_parameter.zig+1-1
...@@ -10,5 +10,5 @@ export fn entry(foo: Foo) void { _ = foo; }...@@ -10,5 +10,5 @@ export fn entry(foo: Foo) void { _ = foo; }
10// target=native10// target=native
11//11//
12// :6:17: error: parameter of type 'tmp.Foo' not allowed in function with calling convention 'C'12// :6:17: error: parameter of type 'tmp.Foo' not allowed in function with calling convention 'C'
13// :6:17: note: only unions with packed or extern layout are extern compatible13// :6:17: note: only extern unions and ABI sized packed unions are extern compatible
14// :1:13: note: union declared here14// :1:13: note: union declared here
test/cases/compile_errors/int_literal_passed_as_variadic_arg.zig deleted-11
...@@ -1,11 +0,0 @@
1extern fn printf([*:0]const u8, ...) c_int;
2
3pub export fn entry() void {
4 _ = printf("%d %d %d %d\n", 1, 2, 3, 4);
5}
6
7// error
8// backend=stage2
9// target=native
10//
11// :4:33: error: integer and float literals in var args function must be casted
test/cases/compile_errors/noalias_param_coersion.zig created+20
...@@ -0,0 +1,20 @@
1pub export fn entry() void {
2 comptime var x: fn (noalias *i32, noalias *i32) void = undefined;
3 x = bar;
4}
5pub export fn entry1() void {
6 comptime var x: fn (*i32, *i32) void = undefined;
7 x = foo;
8}
9
10fn foo(noalias _: *i32, noalias _: *i32) void {}
11fn bar(noalias _: *i32, _: *i32) void {}
12
13// error
14// backend=stage2
15// target=native
16//
17// :3:9: error: expected type 'fn(noalias *i32, noalias *i32) void', found 'fn(noalias *i32, *i32) void'
18// :3:9: note: regular parameter 1 cannot cast into a noalias parameter
19// :7:9: error: expected type 'fn(*i32, *i32) void', found 'fn(noalias *i32, noalias *i32) void'
20// :7:9: note: noalias parameter 0 cannot cast into a regular parameter
test/cases/compile_errors/overflow_in_enum_value_allocation.zig created+14
...@@ -0,0 +1,14 @@
1const Moo = enum(u8) {
2 Last = 255,
3 Over,
4};
5pub export fn entry() void {
6 var y = Moo.Last;
7 _ = y;
8}
9
10// error
11// backend=stage2
12// target=native
13//
14// :3:5: error: enumeration value '256' too large for type 'u8'
test/cases/compile_errors/specify_enum_tag_type_that_is_too_small.zig created+18
...@@ -0,0 +1,18 @@
1const Small = enum (u2) {
2 One,
3 Two,
4 Three,
5 Four,
6 Five,
7};
8
9export fn entry() void {
10 var x = Small.One;
11 _ = x;
12}
13
14// error
15// backend=stage2
16// target=native
17//
18// :6:5: error: enumeration value '4' too large for type 'u2'
test/cases/compile_errors/stage1/obj/overflow_in_enum_value_allocation.zig deleted-14
...@@ -1,14 +0,0 @@
1const Moo = enum(u8) {
2 Last = 255,
3 Over,
4};
5pub fn main() void {
6 var y = Moo.Last;
7 _ = y;
8}
9
10// error
11// backend=stage1
12// target=native
13//
14// tmp.zig:3:5: error: enumeration value 256 too large for type 'u8'
test/cases/compile_errors/stage1/obj/specify_enum_tag_type_that_is_too_small.zig deleted-18
...@@ -1,18 +0,0 @@
1const Small = enum (u2) {
2 One,
3 Two,
4 Three,
5 Four,
6 Five,
7};
8
9export fn entry() void {
10 var x = Small.One;
11 _ = x;
12}
13
14// error
15// backend=stage1
16// target=native
17//
18// tmp.zig:6:5: error: enumeration value 4 too large for type 'u2'
test/cases/compile_errors/try_return.zig created+11
...@@ -0,0 +1,11 @@
1pub fn foo() !void {
2 try return bar();
3}
4pub fn bar() !void {}
5
6// error
7// backend=stage2
8// target=native
9//
10// :2:5: error: unreachable code
11// :2:9: note: control flow is diverted here
test/cases/compile_errors/variadic_arg_validation.zig created+29
...@@ -0,0 +1,29 @@
1extern fn printf([*:0]const u8, ...) c_int;
2
3pub export fn entry() void {
4 _ = printf("%d %d %d %d\n", 1, 2, 3, 4);
5}
6
7pub export fn entry1() void {
8 var arr: [2]u8 = undefined;
9 _ = printf("%d\n", arr);
10}
11
12pub export fn entry2() void {
13 _ = printf("%d\n", @as(u48, 2));
14}
15
16pub export fn entry3() void {
17 _ = printf("%d\n", {});
18}
19
20// error
21// backend=stage2
22// target=native
23//
24// :4:33: error: integer and float literals passed variadic function must be casted to a fixed-size number type
25// :9:24: error: arrays must be passed by reference to variadic function
26// :13:24: error: cannot pass 'u48' to variadic function
27// :13:24: note: only integers with power of two bits are extern compatible
28// :17:24: error: cannot pass 'void' to variadic function
29// :17:24: note: 'void' is a zero bit type; for C 'void' use 'anyopaque'
test/run_translated_c.zig+14-12
...@@ -250,18 +250,20 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {...@@ -250,18 +250,20 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {
250 \\}250 \\}
251 , "");251 , "");
252252
253 cases.add("struct initializer - packed",253 if (@import("builtin").zig_backend == .stage1) {
254 \\#define _NO_CRT_STDIO_INLINE 1254 cases.add("struct initializer - packed",
255 \\#include <stdint.h>255 \\#define _NO_CRT_STDIO_INLINE 1
256 \\#include <stdlib.h>256 \\#include <stdint.h>
257 \\struct s {uint8_t x,y;257 \\#include <stdlib.h>
258 \\ uint32_t z;} __attribute__((packed)) s0 = {1, 2};258 \\struct s {uint8_t x,y;
259 \\int main() {259 \\ uint32_t z;} __attribute__((packed)) s0 = {1, 2};
260 \\ /* sizeof nor offsetof currently supported */260 \\int main() {
261 \\ if (((intptr_t)&s0.z - (intptr_t)&s0.x) != 2) abort();261 \\ /* sizeof nor offsetof currently supported */
262 \\ return 0;262 \\ if (((intptr_t)&s0.z - (intptr_t)&s0.x) != 2) abort();
263 \\}263 \\ return 0;
264 , "");264 \\}
265 , "");
266 }
265267
266 cases.add("cast signed array index to unsigned",268 cases.add("cast signed array index to unsigned",
267 \\#include <stdlib.h>269 \\#include <stdlib.h>
test/standalone.zig+3
...@@ -13,6 +13,8 @@ pub fn addCases(cases: *tests.StandaloneContext) void {...@@ -13,6 +13,8 @@ pub fn addCases(cases: *tests.StandaloneContext) void {
13 cases.add("test/standalone/guess_number/main.zig");13 cases.add("test/standalone/guess_number/main.zig");
14 cases.add("test/standalone/main_return_error/error_u8.zig");14 cases.add("test/standalone/main_return_error/error_u8.zig");
15 cases.add("test/standalone/main_return_error/error_u8_non_zero.zig");15 cases.add("test/standalone/main_return_error/error_u8_non_zero.zig");
16 cases.add("test/standalone/noreturn_call/inline.zig");
17 cases.add("test/standalone/noreturn_call/as_arg.zig");
16 cases.addBuildFile("test/standalone/main_pkg_path/build.zig", .{});18 cases.addBuildFile("test/standalone/main_pkg_path/build.zig", .{});
17 cases.addBuildFile("test/standalone/shared_library/build.zig", .{});19 cases.addBuildFile("test/standalone/shared_library/build.zig", .{});
18 cases.addBuildFile("test/standalone/mix_o_files/build.zig", .{});20 cases.addBuildFile("test/standalone/mix_o_files/build.zig", .{});
...@@ -66,6 +68,7 @@ pub fn addCases(cases: *tests.StandaloneContext) void {...@@ -66,6 +68,7 @@ pub fn addCases(cases: *tests.StandaloneContext) void {
66 if (builtin.os.tag == .linux) {68 if (builtin.os.tag == .linux) {
67 cases.addBuildFile("test/standalone/pie/build.zig", .{});69 cases.addBuildFile("test/standalone/pie/build.zig", .{});
68 }70 }
71 cases.addBuildFile("test/standalone/issue_12706/build.zig", .{});
6972
70 // Ensure the development tools are buildable.73 // Ensure the development tools are buildable.
7174
test/standalone/issue_12706/build.zig created+39
...@@ -0,0 +1,39 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const Builder = std.build.Builder;
4const CrossTarget = std.zig.CrossTarget;
5
6// TODO integrate this with the std.build executor API
7fn isRunnableTarget(t: CrossTarget) bool {
8 if (t.isNative()) return true;
9
10 return (t.getOsTag() == builtin.os.tag and
11 t.getCpuArch() == builtin.cpu.arch);
12}
13
14pub fn build(b: *Builder) void {
15 const mode = b.standardReleaseOptions();
16 const target = b.standardTargetOptions(.{});
17
18 const exe = b.addExecutable("main", "main.zig");
19 exe.setBuildMode(mode);
20 exe.install();
21
22 const c_sources = [_][]const u8{
23 "test.c",
24 };
25
26 exe.addCSourceFiles(&c_sources, &.{});
27 exe.linkLibC();
28
29 exe.setTarget(target);
30 b.default_step.dependOn(&exe.step);
31
32 const test_step = b.step("test", "Test the program");
33 if (isRunnableTarget(target)) {
34 const run_cmd = exe.run();
35 test_step.dependOn(&run_cmd.step);
36 } else {
37 test_step.dependOn(&exe.step);
38 }
39}
test/standalone/issue_12706/main.zig created+12
...@@ -0,0 +1,12 @@
1const std = @import("std");
2extern fn testFnPtr(n: c_int, ...) void;
3
4const val: c_int = 123;
5
6fn func(a: c_int) callconv(.C) void {
7 std.debug.assert(a == val);
8}
9
10pub fn main() void {
11 testFnPtr(2, func, val);
12}
test/standalone/issue_12706/test.c created+11
...@@ -0,0 +1,11 @@
1#include <stdarg.h>
2
3void testFnPtr(int n, ...) {
4 va_list ap;
5 va_start(ap, n);
6
7 void (*fnPtr)(int) = va_arg(ap, void (*)(int));
8 int arg = va_arg(ap, int);
9 fnPtr(arg);
10 va_end(ap);
11}
\ No newline at end of file
test/standalone/noreturn_call/as_arg.zig created+8
...@@ -0,0 +1,8 @@
1const std = @import("std");
2fn foo() noreturn {
3 std.process.exit(0);
4}
5fn bar(_: u8, _: u8) void {}
6pub fn main() void {
7 bar(foo(), @compileError("bad"));
8}
test/standalone/noreturn_call/inline.zig created+10
...@@ -0,0 +1,10 @@
1pub fn main() void {
2 _ = bar();
3}
4inline fn bar() u8 {
5 noret();
6}
7const std = @import("std");
8inline fn noret() noreturn {
9 std.process.exit(0);
10}
test/translate_c.zig+16-14
...@@ -728,20 +728,22 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -728,20 +728,22 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
728 \\}728 \\}
729 });729 });
730730
731 cases.add("struct initializer - packed",731 if (builtin.zig_backend == .stage1) {
732 \\struct {int x,y,z;} __attribute__((packed)) s0 = {1, 2};732 cases.add("struct initializer - packed",
733 , &[_][]const u8{733 \\struct {int x,y,z;} __attribute__((packed)) s0 = {1, 2};
734 \\const struct_unnamed_1 = packed struct {734 , &[_][]const u8{
735 \\ x: c_int,735 \\const struct_unnamed_1 = packed struct {
736 \\ y: c_int,736 \\ x: c_int,
737 \\ z: c_int,737 \\ y: c_int,
738 \\};738 \\ z: c_int,
739 \\pub export var s0: struct_unnamed_1 = struct_unnamed_1{739 \\};
740 \\ .x = @as(c_int, 1),740 \\pub export var s0: struct_unnamed_1 = struct_unnamed_1{
741 \\ .y = @as(c_int, 2),741 \\ .x = @as(c_int, 1),
742 \\ .z = 0,742 \\ .y = @as(c_int, 2),
743 \\};743 \\ .z = 0,
744 });744 \\};
745 });
746 }
745747
746 // Test case temporarily disabled:748 // Test case temporarily disabled:
747 // https://github.com/ziglang/zig/issues/12055749 // https://github.com/ziglang/zig/issues/12055