authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-03-19 14:32:09-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-03-19 14:32:09-04:00
log69e6d455ce8e21835ec3ce268a0533e0e7666e8b
tree8bdc050b60371970ddc8c1d1263a3688e79456aa
parentc6cf40a0c03822cac3112be58c61ca55d436b5d0
parent12f3c461a4429d9c7a0ddbaa6465bf0499a99b8c
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #11228 from Vexu/panic

enable default panic handler for stage2 LLVM

12 files changed, 183 insertions(+), 77 deletions(-)

lib/std/builtin.zig+1-1
...@@ -753,7 +753,7 @@ pub fn default_panic(msg: []const u8, error_return_trace: ?*StackTrace) noreturn...@@ -753,7 +753,7 @@ pub fn default_panic(msg: []const u8, error_return_trace: ?*StackTrace) noreturn
753 @setCold(true);753 @setCold(true);
754 // Until self-hosted catches up with stage1 language features, we have a simpler754 // Until self-hosted catches up with stage1 language features, we have a simpler
755 // default panic function:755 // default panic function:
756 if (builtin.zig_backend != .stage1) {756 if (builtin.zig_backend != .stage1 and builtin.zig_backend != .stage2_llvm) {
757 while (true) {757 while (true) {
758 @breakpoint();758 @breakpoint();
759 }759 }
lib/std/c/darwin.zig+10-6
...@@ -624,8 +624,7 @@ pub const pthread_attr_t = extern struct {...@@ -624,8 +624,7 @@ pub const pthread_attr_t = extern struct {
624 __opaque: [56]u8,624 __opaque: [56]u8,
625};625};
626626
627const pthread_t = std.c.pthread_t;627pub extern "c" fn pthread_threadid_np(thread: ?std.c.pthread_t, thread_id: *u64) c_int;
628pub extern "c" fn pthread_threadid_np(thread: ?pthread_t, thread_id: *u64) c_int;
629pub extern "c" fn pthread_setname_np(name: [*:0]const u8) E;628pub extern "c" fn pthread_setname_np(name: [*:0]const u8) E;
630pub extern "c" fn pthread_getname_np(thread: std.c.pthread_t, name: [*:0]u8, len: usize) E;629pub extern "c" fn pthread_getname_np(thread: std.c.pthread_t, name: [*:0]u8, len: usize) E;
631630
...@@ -921,12 +920,17 @@ pub const siginfo_t = extern struct {...@@ -921,12 +920,17 @@ pub const siginfo_t = extern struct {
921920
922/// Renamed from `sigaction` to `Sigaction` to avoid conflict with function name.921/// Renamed from `sigaction` to `Sigaction` to avoid conflict with function name.
923pub const Sigaction = extern struct {922pub const Sigaction = extern struct {
924 pub const handler_fn = fn (c_int) callconv(.C) void;923 pub usingnamespace if (builtin.zig_backend == .stage1) struct {
925 pub const sigaction_fn = fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void;924 pub const handler_fn = fn (c_int) callconv(.C) void;
925 pub const sigaction_fn = fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void;
926 } else struct {
927 pub const handler_fn = *const fn (c_int) callconv(.C) void;
928 pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void;
929 };
926930
927 handler: extern union {931 handler: extern union {
928 handler: ?handler_fn,932 handler: ?Sigaction.handler_fn,
929 sigaction: ?sigaction_fn,933 sigaction: ?Sigaction.sigaction_fn,
930 },934 },
931 mask: sigset_t,935 mask: sigset_t,
932 flags: c_uint,936 flags: c_uint,
lib/std/debug.zig-1
...@@ -1541,7 +1541,6 @@ pub const ModuleDebugInfo = switch (native_os) {...@@ -1541,7 +1541,6 @@ pub const ModuleDebugInfo = switch (native_os) {
1541 .symbol_name = o_file_di.getSymbolName(relocated_address_o) orelse "???",1541 .symbol_name = o_file_di.getSymbolName(relocated_address_o) orelse "???",
1542 .compile_unit_name = compile_unit.die.getAttrString(o_file_di, DW.AT.name) catch |err| switch (err) {1542 .compile_unit_name = compile_unit.die.getAttrString(o_file_di, DW.AT.name) catch |err| switch (err) {
1543 error.MissingDebugInfo, error.InvalidDebugInfo => "???",1543 error.MissingDebugInfo, error.InvalidDebugInfo => "???",
1544 else => return err,
1545 },1544 },
1546 .line_info = o_file_di.getLineNumberInfo(compile_unit.*, relocated_address_o + addr_off) catch |err| switch (err) {1545 .line_info = o_file_di.getLineNumberInfo(compile_unit.*, relocated_address_o + addr_off) catch |err| switch (err) {
1547 error.MissingDebugInfo, error.InvalidDebugInfo => null,1546 error.MissingDebugInfo, error.InvalidDebugInfo => null,
lib/std/heap/general_purpose_allocator.zig+6-18
...@@ -341,15 +341,9 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {...@@ -341,15 +341,9 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {
341 const slot_index = @intCast(SlotIndex, used_bits_byte * 8 + bit_index);341 const slot_index = @intCast(SlotIndex, used_bits_byte * 8 + bit_index);
342 const stack_trace = bucketStackTrace(bucket, size_class, slot_index, .alloc);342 const stack_trace = bucketStackTrace(bucket, size_class, slot_index, .alloc);
343 const addr = bucket.page + slot_index * size_class;343 const addr = bucket.page + slot_index * size_class;
344 if (builtin.zig_backend == .stage1) {344 log.err("memory address 0x{x} leaked: {s}", .{
345 log.err("memory address 0x{x} leaked: {s}", .{345 @ptrToInt(addr), stack_trace,
346 @ptrToInt(addr), stack_trace,346 });
347 });
348 } else { // TODO
349 log.err("memory address 0x{x} leaked", .{
350 @ptrToInt(addr),
351 });
352 }
353 leaks = true;347 leaks = true;
354 }348 }
355 if (bit_index == math.maxInt(u3))349 if (bit_index == math.maxInt(u3))
...@@ -379,15 +373,9 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {...@@ -379,15 +373,9 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {
379 while (it.next()) |large_alloc| {373 while (it.next()) |large_alloc| {
380 if (config.retain_metadata and large_alloc.freed) continue;374 if (config.retain_metadata and large_alloc.freed) continue;
381 const stack_trace = large_alloc.getStackTrace(.alloc);375 const stack_trace = large_alloc.getStackTrace(.alloc);
382 if (builtin.zig_backend == .stage1) {376 log.err("memory address 0x{x} leaked: {s}", .{
383 log.err("memory address 0x{x} leaked: {s}", .{377 @ptrToInt(large_alloc.bytes.ptr), stack_trace,
384 @ptrToInt(large_alloc.bytes.ptr), stack_trace,378 });
385 });
386 } else { // TODO
387 log.err("memory address 0x{x} leaked", .{
388 @ptrToInt(large_alloc.bytes.ptr),
389 });
390 }
391 leaks = true;379 leaks = true;
392 }380 }
393 return leaks;381 return leaks;
lib/std/macho.zig+3-1
...@@ -624,7 +624,9 @@ pub const segment_command_64 = extern struct {...@@ -624,7 +624,9 @@ pub const segment_command_64 = extern struct {
624 cmd: LC = .SEGMENT_64,624 cmd: LC = .SEGMENT_64,
625625
626 /// includes sizeof section_64 structs626 /// includes sizeof section_64 structs
627 cmdsize: u32 = @sizeOf(segment_command_64),627 cmdsize: u32,
628 // TODO lazy values in stage2
629 // cmdsize: u32 = @sizeOf(segment_command_64),
628630
629 /// segment name631 /// segment name
630 segname: [16]u8,632 segname: [16]u8,
lib/std/os/linux.zig+36-13
...@@ -1080,12 +1080,19 @@ pub fn sigaction(sig: u6, noalias act: ?*const Sigaction, noalias oact: ?*Sigact...@@ -1080,12 +1080,19 @@ pub fn sigaction(sig: u6, noalias act: ?*const Sigaction, noalias oact: ?*Sigact
1080 const mask_size = @sizeOf(@TypeOf(ksa.mask));1080 const mask_size = @sizeOf(@TypeOf(ksa.mask));
10811081
1082 if (act) |new| {1082 if (act) |new| {
1083 const restorer_fn = if ((new.flags & SA.SIGINFO) != 0) restore_rt else restore;1083 const restore_rt_ptr = if (builtin.zig_backend == .stage1) restore_rt else &syscall_bits.restore_rt;
1084 // TODO https://github.com/ziglang/zig/issues/11227
1085 const restore_ptr = if (builtin.zig_backend == .stage1) restore else switch (native_arch) {
1086 .arm, .thumb, .mips, .mipsel, .i386 => &syscall_bits.restore,
1087 .x86_64, .aarch64, .riscv64, .sparcv9, .powerpc, .powerpc64, .powerpc64le => &syscall_bits.restore_rt,
1088 else => unreachable,
1089 };
1090 const restorer_fn = if ((new.flags & SA.SIGINFO) != 0) restore_rt_ptr else restore_ptr;
1084 ksa = k_sigaction{1091 ksa = k_sigaction{
1085 .handler = new.handler.handler,1092 .handler = new.handler.handler,
1086 .flags = new.flags | SA.RESTORER,1093 .flags = new.flags | SA.RESTORER,
1087 .mask = undefined,1094 .mask = undefined,
1088 .restorer = @ptrCast(fn () callconv(.C) void, restorer_fn),1095 .restorer = @ptrCast(k_sigaction_funcs.restorer, restorer_fn),
1089 };1096 };
1090 @memcpy(@ptrCast([*]u8, &ksa.mask), @ptrCast([*]const u8, &new.mask), mask_size);1097 @memcpy(@ptrCast([*]u8, &ksa.mask), @ptrCast([*]const u8, &new.mask), mask_size);
1091 }1098 }
...@@ -3047,39 +3054,55 @@ pub const sigset_t = [1024 / 32]u32;...@@ -3047,39 +3054,55 @@ pub const sigset_t = [1024 / 32]u32;
3047pub const all_mask: sigset_t = [_]u32{0xffffffff} ** sigset_t.len;3054pub const all_mask: sigset_t = [_]u32{0xffffffff} ** sigset_t.len;
3048pub const app_mask: sigset_t = [2]u32{ 0xfffffffc, 0x7fffffff } ++ [_]u32{0xffffffff} ** 30;3055pub const app_mask: sigset_t = [2]u32{ 0xfffffffc, 0x7fffffff } ++ [_]u32{0xffffffff} ** 30;
30493056
3057const k_sigaction_funcs = if (builtin.zig_backend == .stage1) struct {
3058 const handler = ?fn (c_int) callconv(.C) void;
3059 const restorer = fn () callconv(.C) void;
3060} else struct {
3061 const handler = ?*const fn (c_int) callconv(.C) void;
3062 const restorer = *const fn () callconv(.C) void;
3063};
3064
3050pub const k_sigaction = switch (native_arch) {3065pub const k_sigaction = switch (native_arch) {
3051 .mips, .mipsel => extern struct {3066 .mips, .mipsel => extern struct {
3052 flags: c_uint,3067 flags: c_uint,
3053 handler: ?fn (c_int) callconv(.C) void,3068 handler: k_sigaction_funcs.handler,
3054 mask: [4]c_ulong,3069 mask: [4]c_ulong,
3055 restorer: fn () callconv(.C) void,3070 restorer: k_sigaction_funcs.restorer,
3056 },3071 },
3057 .mips64, .mips64el => extern struct {3072 .mips64, .mips64el => extern struct {
3058 flags: c_uint,3073 flags: c_uint,
3059 handler: ?fn (c_int) callconv(.C) void,3074 handler: k_sigaction_funcs.handler,
3060 mask: [2]c_ulong,3075 mask: [2]c_ulong,
3061 restorer: fn () callconv(.C) void,3076 restorer: k_sigaction_funcs.restorer,
3062 },3077 },
3063 else => extern struct {3078 else => extern struct {
3064 handler: ?fn (c_int) callconv(.C) void,3079 handler: k_sigaction_funcs.handler,
3065 flags: c_ulong,3080 flags: c_ulong,
3066 restorer: fn () callconv(.C) void,3081 restorer: k_sigaction_funcs.restorer,
3067 mask: [2]c_uint,3082 mask: [2]c_uint,
3068 },3083 },
3069};3084};
30703085
3071/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.3086/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
3072pub const Sigaction = extern struct {3087pub const Sigaction = extern struct {
3073 pub const handler_fn = fn (c_int) callconv(.C) void;3088 pub usingnamespace if (builtin.zig_backend == .stage1) struct {
3074 pub const sigaction_fn = fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void;3089 pub const handler_fn = fn (c_int) callconv(.C) void;
3090 pub const sigaction_fn = fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void;
3091 } else struct {
3092 pub const handler_fn = *const fn (c_int) callconv(.C) void;
3093 pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void;
3094 };
30753095
3076 handler: extern union {3096 handler: extern union {
3077 handler: ?handler_fn,3097 handler: ?Sigaction.handler_fn,
3078 sigaction: ?sigaction_fn,3098 sigaction: ?Sigaction.sigaction_fn,
3079 },3099 },
3080 mask: sigset_t,3100 mask: sigset_t,
3081 flags: c_uint,3101 flags: c_uint,
3082 restorer: ?fn () callconv(.C) void = null,3102 restorer: ?if (builtin.zig_backend == .stage1)
3103 fn () callconv(.C) void
3104 else
3105 *const fn () callconv(.C) void = null,
3083};3106};
30843107
3085pub const empty_sigset = [_]u32{0} ** @typeInfo(sigset_t).Array.len;3108pub const empty_sigset = [_]u32{0} ** @typeInfo(sigset_t).Array.len;
src/Sema.zig+88-29
...@@ -131,6 +131,9 @@ pub const Block = struct {...@@ -131,6 +131,9 @@ pub const Block = struct {
131131
132 c_import_buf: ?*std.ArrayList(u8) = null,132 c_import_buf: ?*std.ArrayList(u8) = null,
133133
134 /// type of `err` in `else => |err|`
135 switch_else_err_ty: ?Type = null,
136
134 const Param = struct {137 const Param = struct {
135 /// `noreturn` means `anytype`.138 /// `noreturn` means `anytype`.
136 ty: Type,139 ty: Type,
...@@ -189,6 +192,7 @@ pub const Block = struct {...@@ -189,6 +192,7 @@ pub const Block = struct {
189 .runtime_index = parent.runtime_index,192 .runtime_index = parent.runtime_index,
190 .want_safety = parent.want_safety,193 .want_safety = parent.want_safety,
191 .c_import_buf = parent.c_import_buf,194 .c_import_buf = parent.c_import_buf,
195 .switch_else_err_ty = parent.switch_else_err_ty,
192 };196 };
193 }197 }
194198
...@@ -3930,6 +3934,23 @@ fn analyzeBlockBody(...@@ -3930,6 +3934,23 @@ fn analyzeBlockBody(
3930 // to emit a jump instruction to after the block when it encounters the break.3934 // to emit a jump instruction to after the block when it encounters the break.
3931 try parent_block.instructions.append(gpa, merges.block_inst);3935 try parent_block.instructions.append(gpa, merges.block_inst);
3932 const resolved_ty = try sema.resolvePeerTypes(parent_block, src, merges.results.items, .none);3936 const resolved_ty = try sema.resolvePeerTypes(parent_block, src, merges.results.items, .none);
3937
3938 const type_src = src; // TODO: better source location
3939 const valid_rt = try sema.validateRunTimeType(child_block, type_src, resolved_ty, false);
3940 if (!valid_rt) {
3941 const msg = msg: {
3942 const msg = try sema.errMsg(child_block, type_src, "value with comptime only type '{}' depends on runtime control flow", .{resolved_ty});
3943 errdefer msg.destroy(sema.gpa);
3944
3945 const runtime_src = child_block.runtime_cond orelse child_block.runtime_loop.?;
3946 try sema.errNote(child_block, runtime_src, msg, "runtime control flow here", .{});
3947
3948 try sema.explainWhyTypeIsComptime(child_block, type_src, msg, type_src.toSrcLoc(child_block.src_decl), resolved_ty);
3949
3950 break :msg msg;
3951 };
3952 return sema.failWithOwnedErrorMsg(child_block, msg);
3953 }
3933 const ty_inst = try sema.addType(resolved_ty);3954 const ty_inst = try sema.addType(resolved_ty);
3934 try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Block).Struct.fields.len +3955 try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Block).Struct.fields.len +
3935 child_block.instructions.items.len);3956 child_block.instructions.items.len);
...@@ -4191,6 +4212,11 @@ fn zirBreak(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) CompileError...@@ -4191,6 +4212,11 @@ fn zirBreak(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) CompileError
4191 const br_ref = try start_block.addBr(label.merges.block_inst, operand);4212 const br_ref = try start_block.addBr(label.merges.block_inst, operand);
4192 try label.merges.results.append(sema.gpa, operand);4213 try label.merges.results.append(sema.gpa, operand);
4193 try label.merges.br_list.append(sema.gpa, Air.refToIndex(br_ref).?);4214 try label.merges.br_list.append(sema.gpa, Air.refToIndex(br_ref).?);
4215 block.runtime_index += 1;
4216 if (block.runtime_cond == null and block.runtime_loop == null) {
4217 block.runtime_cond = start_block.runtime_cond orelse start_block.runtime_loop;
4218 block.runtime_loop = start_block.runtime_loop;
4219 }
4194 return inst;4220 return inst;
4195 }4221 }
4196 }4222 }
...@@ -6692,12 +6718,6 @@ fn zirSwitchCapture(...@@ -6692,12 +6718,6 @@ fn zirSwitchCapture(
66926718
6693 if (capture_info.prong_index == std.math.maxInt(@TypeOf(capture_info.prong_index))) {6719 if (capture_info.prong_index == std.math.maxInt(@TypeOf(capture_info.prong_index))) {
6694 // It is the else/`_` prong.6720 // It is the else/`_` prong.
6695 switch (operand_ty.zigTypeTag()) {
6696 .ErrorSet => {
6697 return sema.fail(block, operand_src, "TODO implement Sema for zirSwitchCaptureElse for error sets", .{});
6698 },
6699 else => {},
6700 }
6701 if (is_ref) {6721 if (is_ref) {
6702 assert(operand_is_ref);6722 assert(operand_is_ref);
6703 return operand_ptr;6723 return operand_ptr;
...@@ -6708,7 +6728,10 @@ fn zirSwitchCapture(...@@ -6708,7 +6728,10 @@ fn zirSwitchCapture(
6708 else6728 else
6709 operand_ptr;6729 operand_ptr;
67106730
6711 return operand;6731 switch (operand_ty.zigTypeTag()) {
6732 .ErrorSet => return sema.bitCast(block, block.switch_else_err_ty.?, operand, operand_src),
6733 else => return operand,
6734 }
6712 }6735 }
67136736
6714 if (is_multi) {6737 if (is_multi) {
...@@ -6885,6 +6908,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -6885,6 +6908,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
68856908
6886 const operand_ty = sema.typeOf(operand);6909 const operand_ty = sema.typeOf(operand);
68876910
6911 var else_error_ty: ?Type = null;
6912
6888 // Validate usage of '_' prongs.6913 // Validate usage of '_' prongs.
6889 if (special_prong == .under and !operand_ty.isNonexhaustiveEnum()) {6914 if (special_prong == .under and !operand_ty.isNonexhaustiveEnum()) {
6890 const msg = msg: {6915 const msg = msg: {
...@@ -7077,6 +7102,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -7077,6 +7102,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
7077 .{},7102 .{},
7078 );7103 );
7079 }7104 }
7105 else_error_ty = Type.@"anyerror";
7080 } else {7106 } else {
7081 var maybe_msg: ?*Module.ErrorMsg = null;7107 var maybe_msg: ?*Module.ErrorMsg = null;
7082 errdefer if (maybe_msg) |msg| msg.destroy(sema.gpa);7108 errdefer if (maybe_msg) |msg| msg.destroy(sema.gpa);
...@@ -7121,6 +7147,17 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -7121,6 +7147,17 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
7121 .{},7147 .{},
7122 );7148 );
7123 }7149 }
7150
7151 const error_names = operand_ty.errorSetNames();
7152 var names: Module.ErrorSet.NameMap = .{};
7153 try names.ensureUnusedCapacity(sema.arena, error_names.len);
7154 for (error_names) |error_name| {
7155 if (seen_errors.contains(error_name)) continue;
7156
7157 names.putAssumeCapacityNoClobber(error_name, {});
7158 }
7159
7160 else_error_ty = try Type.Tag.error_set_merged.create(sema.arena, names);
7124 }7161 }
7125 },7162 },
7126 .Union => return sema.fail(block, src, "TODO validate switch .Union", .{}),7163 .Union => return sema.fail(block, src, "TODO validate switch .Union", .{}),
...@@ -7398,6 +7435,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -7398,6 +7435,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
7398 .label = &label,7435 .label = &label,
7399 .inlining = block.inlining,7436 .inlining = block.inlining,
7400 .is_comptime = block.is_comptime,7437 .is_comptime = block.is_comptime,
7438 .switch_else_err_ty = else_error_ty,
7401 };7439 };
7402 const merges = &child_block.label.?.merges;7440 const merges = &child_block.label.?.merges;
7403 defer child_block.instructions.deinit(gpa);7441 defer child_block.instructions.deinit(gpa);
...@@ -15447,6 +15485,26 @@ fn validateVarType(...@@ -15447,6 +15485,26 @@ fn validateVarType(
15447 var_ty: Type,15485 var_ty: Type,
15448 is_extern: bool,15486 is_extern: bool,
15449) CompileError!void {15487) CompileError!void {
15488 if (try sema.validateRunTimeType(block, src, var_ty, is_extern)) return;
15489
15490 const msg = msg: {
15491 const msg = try sema.errMsg(block, src, "variable of type '{}' must be const or comptime", .{var_ty});
15492 errdefer msg.destroy(sema.gpa);
15493
15494 try sema.explainWhyTypeIsComptime(block, src, msg, src.toSrcLoc(block.src_decl), var_ty);
15495
15496 break :msg msg;
15497 };
15498 return sema.failWithOwnedErrorMsg(block, msg);
15499}
15500
15501fn validateRunTimeType(
15502 sema: *Sema,
15503 block: *Block,
15504 src: LazySrcLoc,
15505 var_ty: Type,
15506 is_extern: bool,
15507) CompileError!bool {
15450 var ty = var_ty;15508 var ty = var_ty;
15451 while (true) switch (ty.zigTypeTag()) {15509 while (true) switch (ty.zigTypeTag()) {
15452 .Bool,15510 .Bool,
...@@ -15457,7 +15515,7 @@ fn validateVarType(...@@ -15457,7 +15515,7 @@ fn validateVarType(
15457 .Frame,15515 .Frame,
15458 .AnyFrame,15516 .AnyFrame,
15459 .Void,15517 .Void,
15460 => return,15518 => return true,
1546115519
15462 .BoundFn,15520 .BoundFn,
15463 .ComptimeFloat,15521 .ComptimeFloat,
...@@ -15468,21 +15526,21 @@ fn validateVarType(...@@ -15468,21 +15526,21 @@ fn validateVarType(
15468 .Undefined,15526 .Undefined,
15469 .Null,15527 .Null,
15470 .Fn,15528 .Fn,
15471 => break,15529 => return false,
1547215530
15473 .Pointer => {15531 .Pointer => {
15474 const elem_ty = ty.childType();15532 const elem_ty = ty.childType();
15475 switch (elem_ty.zigTypeTag()) {15533 switch (elem_ty.zigTypeTag()) {
15476 .Opaque, .Fn => return,15534 .Opaque, .Fn => return true,
15477 else => ty = elem_ty,15535 else => ty = elem_ty,
15478 }15536 }
15479 },15537 },
15480 .Opaque => if (is_extern) return else break,15538 .Opaque => return is_extern,
1548115539
15482 .Optional => {15540 .Optional => {
15483 var buf: Type.Payload.ElemType = undefined;15541 var buf: Type.Payload.ElemType = undefined;
15484 const child_ty = ty.optionalChild(&buf);15542 const child_ty = ty.optionalChild(&buf);
15485 return validateVarType(sema, block, src, child_ty, is_extern);15543 return validateRunTimeType(sema, block, src, child_ty, is_extern);
15486 },15544 },
15487 .Array, .Vector => ty = ty.elemType(),15545 .Array, .Vector => ty = ty.elemType(),
1548815546
...@@ -15490,23 +15548,10 @@ fn validateVarType(...@@ -15490,23 +15548,10 @@ fn validateVarType(
1549015548
15491 .Struct, .Union => {15549 .Struct, .Union => {
15492 const resolved_ty = try sema.resolveTypeFields(block, src, ty);15550 const resolved_ty = try sema.resolveTypeFields(block, src, ty);
15493 if (try sema.typeRequiresComptime(block, src, resolved_ty)) {15551 const needs_comptime = try sema.typeRequiresComptime(block, src, resolved_ty);
15494 break;15552 return !needs_comptime;
15495 } else {
15496 return;
15497 }
15498 },15553 },
15499 } else unreachable; // TODO should not need else unreachable
15500
15501 const msg = msg: {
15502 const msg = try sema.errMsg(block, src, "variable of type '{}' must be const or comptime", .{var_ty});
15503 errdefer msg.destroy(sema.gpa);
15504
15505 try sema.explainWhyTypeIsComptime(block, src, msg, src.toSrcLoc(block.src_decl), var_ty);
15506
15507 break :msg msg;
15508 };15554 };
15509 return sema.failWithOwnedErrorMsg(block, msg);
15510}15555}
1551115556
15512fn explainWhyTypeIsComptime(15557fn explainWhyTypeIsComptime(
...@@ -18494,8 +18539,8 @@ pub fn bitCastVal(...@@ -18494,8 +18539,8 @@ pub fn bitCastVal(
18494 const abi_size = try sema.usizeCast(block, src, old_ty.abiSize(target));18539 const abi_size = try sema.usizeCast(block, src, old_ty.abiSize(target));
18495 const buffer = try sema.gpa.alloc(u8, abi_size);18540 const buffer = try sema.gpa.alloc(u8, abi_size);
18496 defer sema.gpa.free(buffer);18541 defer sema.gpa.free(buffer);
18497 val.writeToMemory(old_ty, target, buffer);18542 val.writeToMemory(old_ty, sema.mod, buffer);
18498 return Value.readFromMemory(new_ty, target, buffer[buffer_offset..], sema.arena);18543 return Value.readFromMemory(new_ty, sema.mod, buffer[buffer_offset..], sema.arena);
18499}18544}
1850018545
18501fn coerceArrayPtrToSlice(18546fn coerceArrayPtrToSlice(
...@@ -20351,6 +20396,20 @@ pub fn resolveTypeFully(...@@ -20351,6 +20396,20 @@ pub fn resolveTypeFully(
20351 return resolveTypeFully(sema, block, src, ty.optionalChild(&buf));20396 return resolveTypeFully(sema, block, src, ty.optionalChild(&buf));
20352 },20397 },
20353 .ErrorUnion => return resolveTypeFully(sema, block, src, ty.errorUnionPayload()),20398 .ErrorUnion => return resolveTypeFully(sema, block, src, ty.errorUnionPayload()),
20399 .Fn => {
20400 const info = ty.fnInfo();
20401 if (info.is_generic) {
20402 // Resolving of generic function types is defeerred to when
20403 // the function is instantiated.
20404 return;
20405 }
20406 for (info.param_types) |param_ty| {
20407 const param_ty_src = src; // TODO better source location
20408 try sema.resolveTypeFully(block, param_ty_src, param_ty);
20409 }
20410 const return_ty_src = src; // TODO better source location
20411 try sema.resolveTypeFully(block, return_ty_src, info.return_type);
20412 },
20354 else => {},20413 else => {},
20355 }20414 }
20356}20415}
src/link/MachO.zig+5
...@@ -4301,6 +4301,7 @@ fn populateMissingMetadata(self: *MachO) !void {...@@ -4301,6 +4301,7 @@ fn populateMissingMetadata(self: *MachO) !void {
4301 .inner = .{4301 .inner = .{
4302 .segname = makeStaticString("__PAGEZERO"),4302 .segname = makeStaticString("__PAGEZERO"),
4303 .vmsize = pagezero_vmsize,4303 .vmsize = pagezero_vmsize,
4304 .cmdsize = @sizeOf(macho.segment_command_64),
4304 },4305 },
4305 },4306 },
4306 });4307 });
...@@ -4326,6 +4327,7 @@ fn populateMissingMetadata(self: *MachO) !void {...@@ -4326,6 +4327,7 @@ fn populateMissingMetadata(self: *MachO) !void {
4326 .filesize = needed_size,4327 .filesize = needed_size,
4327 .maxprot = macho.PROT.READ | macho.PROT.EXEC,4328 .maxprot = macho.PROT.READ | macho.PROT.EXEC,
4328 .initprot = macho.PROT.READ | macho.PROT.EXEC,4329 .initprot = macho.PROT.READ | macho.PROT.EXEC,
4330 .cmdsize = @sizeOf(macho.segment_command_64),
4329 },4331 },
4330 },4332 },
4331 });4333 });
...@@ -4431,6 +4433,7 @@ fn populateMissingMetadata(self: *MachO) !void {...@@ -4431,6 +4433,7 @@ fn populateMissingMetadata(self: *MachO) !void {
4431 .filesize = needed_size,4433 .filesize = needed_size,
4432 .maxprot = macho.PROT.READ | macho.PROT.WRITE,4434 .maxprot = macho.PROT.READ | macho.PROT.WRITE,
4433 .initprot = macho.PROT.READ | macho.PROT.WRITE,4435 .initprot = macho.PROT.READ | macho.PROT.WRITE,
4436 .cmdsize = @sizeOf(macho.segment_command_64),
4434 },4437 },
4435 },4438 },
4436 });4439 });
...@@ -4480,6 +4483,7 @@ fn populateMissingMetadata(self: *MachO) !void {...@@ -4480,6 +4483,7 @@ fn populateMissingMetadata(self: *MachO) !void {
4480 .filesize = needed_size,4483 .filesize = needed_size,
4481 .maxprot = macho.PROT.READ | macho.PROT.WRITE,4484 .maxprot = macho.PROT.READ | macho.PROT.WRITE,
4482 .initprot = macho.PROT.READ | macho.PROT.WRITE,4485 .initprot = macho.PROT.READ | macho.PROT.WRITE,
4486 .cmdsize = @sizeOf(macho.segment_command_64),
4483 },4487 },
4484 },4488 },
4485 });4489 });
...@@ -4589,6 +4593,7 @@ fn populateMissingMetadata(self: *MachO) !void {...@@ -4589,6 +4593,7 @@ fn populateMissingMetadata(self: *MachO) !void {
4589 .fileoff = fileoff,4593 .fileoff = fileoff,
4590 .maxprot = macho.PROT.READ,4594 .maxprot = macho.PROT.READ,
4591 .initprot = macho.PROT.READ,4595 .initprot = macho.PROT.READ,
4596 .cmdsize = @sizeOf(macho.segment_command_64),
4592 },4597 },
4593 },4598 },
4594 });4599 });
src/link/MachO/DebugSymbols.zig+1
...@@ -148,6 +148,7 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: Allocator) !void...@@ -148,6 +148,7 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: Allocator) !void
148 .vmsize = needed_size,148 .vmsize = needed_size,
149 .fileoff = fileoff,149 .fileoff = fileoff,
150 .filesize = needed_size,150 .filesize = needed_size,
151 .cmdsize = @sizeOf(macho.segment_command_64),
151 },152 },
152 },153 },
153 });154 });
src/value.zig+26-6
...@@ -1042,7 +1042,8 @@ pub const Value = extern union {...@@ -1042,7 +1042,8 @@ pub const Value = extern union {
1042 };1042 };
1043 }1043 }
10441044
1045 pub fn writeToMemory(val: Value, ty: Type, target: Target, buffer: []u8) void {1045 pub fn writeToMemory(val: Value, ty: Type, mod: *Module, buffer: []u8) void {
1046 const target = mod.getTarget();
1046 if (val.isUndef()) {1047 if (val.isUndef()) {
1047 const size = @intCast(usize, ty.abiSize(target));1048 const size = @intCast(usize, ty.abiSize(target));
1048 std.mem.set(u8, buffer[0..size], 0xaa);1049 std.mem.set(u8, buffer[0..size], 0xaa);
...@@ -1081,7 +1082,7 @@ pub const Value = extern union {...@@ -1081,7 +1082,7 @@ pub const Value = extern union {
1081 var buf_off: usize = 0;1082 var buf_off: usize = 0;
1082 while (elem_i < len) : (elem_i += 1) {1083 while (elem_i < len) : (elem_i += 1) {
1083 const elem_val = val.elemValueBuffer(elem_i, &elem_value_buf);1084 const elem_val = val.elemValueBuffer(elem_i, &elem_value_buf);
1084 writeToMemory(elem_val, elem_ty, target, buffer[buf_off..]);1085 writeToMemory(elem_val, elem_ty, mod, buffer[buf_off..]);
1085 buf_off += elem_size;1086 buf_off += elem_size;
1086 }1087 }
1087 },1088 },
...@@ -1092,7 +1093,7 @@ pub const Value = extern union {...@@ -1092,7 +1093,7 @@ pub const Value = extern union {
1092 const field_vals = val.castTag(.aggregate).?.data;1093 const field_vals = val.castTag(.aggregate).?.data;
1093 for (fields) |field, i| {1094 for (fields) |field, i| {
1094 const off = @intCast(usize, ty.structFieldOffset(i, target));1095 const off = @intCast(usize, ty.structFieldOffset(i, target));
1095 writeToMemory(field_vals[i], field.ty, target, buffer[off..]);1096 writeToMemory(field_vals[i], field.ty, mod, buffer[off..]);
1096 }1097 }
1097 },1098 },
1098 .Packed => {1099 .Packed => {
...@@ -1105,6 +1106,12 @@ pub const Value = extern union {...@@ -1105,6 +1106,12 @@ pub const Value = extern union {
1105 host_int.writeTwosComplement(buffer, bit_size, abi_size, target.cpu.arch.endian());1106 host_int.writeTwosComplement(buffer, bit_size, abi_size, target.cpu.arch.endian());
1106 },1107 },
1107 },1108 },
1109 .ErrorSet => {
1110 // TODO revisit this when we have the concept of the error tag type
1111 const Int = u16;
1112 const int = mod.global_error_set.get(val.castTag(.@"error").?.data.name).?;
1113 std.mem.writeInt(Int, buffer[0..@sizeOf(Int)], @intCast(Int, int), target.cpu.arch.endian());
1114 },
1108 else => @panic("TODO implement writeToMemory for more types"),1115 else => @panic("TODO implement writeToMemory for more types"),
1109 }1116 }
1110 }1117 }
...@@ -1153,10 +1160,11 @@ pub const Value = extern union {...@@ -1153,10 +1160,11 @@ pub const Value = extern union {
11531160
1154 pub fn readFromMemory(1161 pub fn readFromMemory(
1155 ty: Type,1162 ty: Type,
1156 target: Target,1163 mod: *Module,
1157 buffer: []const u8,1164 buffer: []const u8,
1158 arena: Allocator,1165 arena: Allocator,
1159 ) Allocator.Error!Value {1166 ) Allocator.Error!Value {
1167 const target = mod.getTarget();
1160 switch (ty.zigTypeTag()) {1168 switch (ty.zigTypeTag()) {
1161 .Int => {1169 .Int => {
1162 if (buffer.len == 0) return Value.zero;1170 if (buffer.len == 0) return Value.zero;
...@@ -1184,7 +1192,7 @@ pub const Value = extern union {...@@ -1184,7 +1192,7 @@ pub const Value = extern union {
1184 const elems = try arena.alloc(Value, @intCast(usize, ty.arrayLen()));1192 const elems = try arena.alloc(Value, @intCast(usize, ty.arrayLen()));
1185 var offset: usize = 0;1193 var offset: usize = 0;
1186 for (elems) |*elem| {1194 for (elems) |*elem| {
1187 elem.* = try readFromMemory(elem_ty, target, buffer[offset..], arena);1195 elem.* = try readFromMemory(elem_ty, mod, buffer[offset..], arena);
1188 offset += @intCast(usize, elem_size);1196 offset += @intCast(usize, elem_size);
1189 }1197 }
1190 return Tag.aggregate.create(arena, elems);1198 return Tag.aggregate.create(arena, elems);
...@@ -1196,7 +1204,7 @@ pub const Value = extern union {...@@ -1196,7 +1204,7 @@ pub const Value = extern union {
1196 const field_vals = try arena.alloc(Value, fields.len);1204 const field_vals = try arena.alloc(Value, fields.len);
1197 for (fields) |field, i| {1205 for (fields) |field, i| {
1198 const off = @intCast(usize, ty.structFieldOffset(i, target));1206 const off = @intCast(usize, ty.structFieldOffset(i, target));
1199 field_vals[i] = try readFromMemory(field.ty, target, buffer[off..], arena);1207 field_vals[i] = try readFromMemory(field.ty, mod, buffer[off..], arena);
1200 }1208 }
1201 return Tag.aggregate.create(arena, field_vals);1209 return Tag.aggregate.create(arena, field_vals);
1202 },1210 },
...@@ -1212,6 +1220,18 @@ pub const Value = extern union {...@@ -1212,6 +1220,18 @@ pub const Value = extern union {
1212 return intToPackedStruct(ty, target, bigint.toConst(), arena);1220 return intToPackedStruct(ty, target, bigint.toConst(), arena);
1213 },1221 },
1214 },1222 },
1223 .ErrorSet => {
1224 // TODO revisit this when we have the concept of the error tag type
1225 const Int = u16;
1226 const int = std.mem.readInt(Int, buffer[0..@sizeOf(Int)], target.cpu.arch.endian());
1227
1228 const payload = try arena.create(Value.Payload.Error);
1229 payload.* = .{
1230 .base = .{ .tag = .@"error" },
1231 .data = .{ .name = mod.error_name_list.items[@intCast(usize, int)] },
1232 };
1233 return Value.initPayload(&payload.base);
1234 },
1215 else => @panic("TODO implement readFromMemory for more types"),1235 else => @panic("TODO implement readFromMemory for more types"),
1216 }1236 }
1217 }1237 }
test/behavior/basic.zig+2-1
...@@ -331,6 +331,7 @@ fn copy(src: *const u64, dst: *u64) void {...@@ -331,6 +331,7 @@ fn copy(src: *const u64, dst: *u64) void {
331}331}
332332
333test "call result of if else expression" {333test "call result of if else expression" {
334 if (builtin.zig_backend == .stage1) return error.SkipZigTest; // stage1 has different function pointers
334 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;335 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
335 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;336 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
336 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;337 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
...@@ -341,7 +342,7 @@ test "call result of if else expression" {...@@ -341,7 +342,7 @@ test "call result of if else expression" {
341 try expect(mem.eql(u8, f2(false), "b"));342 try expect(mem.eql(u8, f2(false), "b"));
342}343}
343fn f2(x: bool) []const u8 {344fn f2(x: bool) []const u8 {
344 return (if (x) fA else fB)();345 return (if (x) &fA else &fB)();
345}346}
346347
347test "memcpy and memset intrinsics" {348test "memcpy and memset intrinsics" {
test/behavior/switch.zig+5-1
...@@ -430,7 +430,11 @@ test "switch on integer with else capturing expr" {...@@ -430,7 +430,11 @@ test "switch on integer with else capturing expr" {
430}430}
431431
432test "else prong of switch on error set excludes other cases" {432test "else prong of switch on error set excludes other cases" {
433 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO433 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
434 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
435 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
436 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
437 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
434438
435 const S = struct {439 const S = struct {
436 fn doTheTest() !void {440 fn doTheTest() !void {