mirror of
https://github.com/ziglang/zig.git
synced 2024-11-15 16:45:27 +00:00
parent
ed73429926
commit
e60db701d1
@ -891,6 +891,10 @@ pub const panic_messages = struct {
|
||||
pub const corrupt_switch = "switch on corrupt value";
|
||||
pub const shift_rhs_too_big = "shift amount is greater than the type size";
|
||||
pub const invalid_enum_value = "invalid enum value";
|
||||
pub const sentinel_mismatch = "sentinel mismatch";
|
||||
pub const unwrap_error = "attempt to unwrap error";
|
||||
pub const index_out_of_bounds = "index out of bounds";
|
||||
pub const start_index_greater_than_end = "start index is larger than end index";
|
||||
};
|
||||
|
||||
pub noinline fn returnError(st: *StackTrace) void {
|
||||
|
@ -101,6 +101,7 @@ debug_compile_errors: bool,
|
||||
job_queued_compiler_rt_lib: bool = false,
|
||||
job_queued_compiler_rt_obj: bool = false,
|
||||
alloc_failure_occurred: bool = false,
|
||||
formatted_panics: bool = false,
|
||||
|
||||
c_source_files: []const CSourceFile,
|
||||
clang_argv: []const []const u8,
|
||||
@ -937,6 +938,7 @@ pub const InitOptions = struct {
|
||||
use_stage1: ?bool = null,
|
||||
single_threaded: ?bool = null,
|
||||
strip: ?bool = null,
|
||||
formatted_panics: ?bool = null,
|
||||
rdynamic: bool = false,
|
||||
function_sections: bool = false,
|
||||
no_builtin: bool = false,
|
||||
@ -1457,6 +1459,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
|
||||
.Debug => @as(u8, 0),
|
||||
else => @as(u8, 3),
|
||||
};
|
||||
const formatted_panics = options.formatted_panics orelse (options.optimize_mode == .Debug);
|
||||
|
||||
// We put everything into the cache hash that *cannot be modified
|
||||
// during an incremental update*. For example, one cannot change the
|
||||
@ -1551,6 +1554,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
|
||||
hash.addOptionalBytes(options.test_name_prefix);
|
||||
hash.add(options.skip_linker_dependencies);
|
||||
hash.add(options.parent_compilation_link_libc);
|
||||
hash.add(formatted_panics);
|
||||
|
||||
// In the case of incremental cache mode, this `zig_cache_artifact_directory`
|
||||
// is computed based on a hash of non-linker inputs, and it is where all
|
||||
@ -1957,6 +1961,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
|
||||
.owned_link_dir = owned_link_dir,
|
||||
.color = options.color,
|
||||
.reference_trace = options.reference_trace,
|
||||
.formatted_panics = formatted_panics,
|
||||
.time_report = options.time_report,
|
||||
.stack_report = options.stack_report,
|
||||
.unwind_tables = unwind_tables,
|
||||
|
76
src/Sema.zig
76
src/Sema.zig
@ -667,9 +667,9 @@ pub const Block = struct {
|
||||
return result_index;
|
||||
}
|
||||
|
||||
fn addUnreachable(block: *Block, src: LazySrcLoc, safety_check: bool) !void {
|
||||
fn addUnreachable(block: *Block, safety_check: bool) !void {
|
||||
if (safety_check and block.wantSafety()) {
|
||||
_ = try block.sema.safetyPanic(block, src, .unreach);
|
||||
try block.sema.safetyPanic(block, .unreach);
|
||||
} else {
|
||||
_ = try block.addNoOp(.unreach);
|
||||
}
|
||||
@ -5003,7 +5003,8 @@ fn zirPanic(sema: *Sema, block: *Block, inst: Zir.Inst.Index, force_comptime: bo
|
||||
if (block.is_comptime or force_comptime) {
|
||||
return sema.fail(block, src, "encountered @panic at comptime", .{});
|
||||
}
|
||||
return sema.panicWithMsg(block, src, msg_inst);
|
||||
try sema.panicWithMsg(block, src, msg_inst);
|
||||
return always_noreturn;
|
||||
}
|
||||
|
||||
fn zirLoop(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
|
||||
@ -7962,7 +7963,7 @@ fn analyzeErrUnionPayload(
|
||||
if (safety_check and block.wantSafety() and
|
||||
!err_union_ty.errorUnionSet().errorSetIsEmpty())
|
||||
{
|
||||
try sema.panicUnwrapError(block, src, operand, .unwrap_errunion_err, .is_non_err);
|
||||
try sema.panicUnwrapError(block, operand, .unwrap_errunion_err, .is_non_err);
|
||||
}
|
||||
|
||||
return block.addTyOp(.unwrap_errunion_payload, payload_ty, operand);
|
||||
@ -8047,7 +8048,7 @@ fn analyzeErrUnionPayloadPtr(
|
||||
if (safety_check and block.wantSafety() and
|
||||
!err_union_ty.errorUnionSet().errorSetIsEmpty())
|
||||
{
|
||||
try sema.panicUnwrapError(block, src, operand, .unwrap_errunion_err_ptr, .is_non_err_ptr);
|
||||
try sema.panicUnwrapError(block, operand, .unwrap_errunion_err_ptr, .is_non_err_ptr);
|
||||
}
|
||||
|
||||
const air_tag: Air.Inst.Tag = if (initializing)
|
||||
@ -9542,7 +9543,7 @@ fn zirSwitchCapture(
|
||||
.ErrorSet => if (block.switch_else_err_ty) |some| {
|
||||
return sema.bitCast(block, some, operand, operand_src);
|
||||
} else {
|
||||
try block.addUnreachable(operand_src, false);
|
||||
try block.addUnreachable(false);
|
||||
return Air.Inst.Ref.unreachable_value;
|
||||
},
|
||||
else => return operand,
|
||||
@ -10975,7 +10976,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
|
||||
// that it is unreachable.
|
||||
if (case_block.wantSafety()) {
|
||||
try sema.zirDbgStmt(&case_block, cond_dbg_node_index);
|
||||
_ = try sema.safetyPanic(&case_block, src, .corrupt_switch);
|
||||
try sema.safetyPanic(&case_block, .corrupt_switch);
|
||||
} else {
|
||||
_ = try case_block.addNoOp(.unreach);
|
||||
}
|
||||
@ -11304,6 +11305,11 @@ fn maybeErrorUnwrap(sema: *Sema, block: *Block, body: []const Zir.Inst.Index, op
|
||||
const inst_data = sema.code.instructions.items(.data)[inst].@"unreachable";
|
||||
const src = inst_data.src();
|
||||
|
||||
if (!sema.mod.comp.formatted_panics) {
|
||||
try sema.safetyPanic(block, .unwrap_error);
|
||||
return true;
|
||||
}
|
||||
|
||||
const panic_fn = try sema.getBuiltin("panicUnwrapError");
|
||||
const err_return_trace = try sema.getErrorReturnTrace(block);
|
||||
const args: [2]Air.Inst.Ref = .{ err_return_trace, operand };
|
||||
@ -16513,7 +16519,7 @@ fn zirUnreachable(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
|
||||
return sema.fail(block, src, "reached unreachable code", .{});
|
||||
}
|
||||
// TODO Add compile error for @optimizeFor occurring too late in a scope.
|
||||
try block.addUnreachable(src, true);
|
||||
try block.addUnreachable(true);
|
||||
return always_noreturn;
|
||||
}
|
||||
|
||||
@ -22128,6 +22134,10 @@ pub const PanicId = enum {
|
||||
corrupt_switch,
|
||||
shift_rhs_too_big,
|
||||
invalid_enum_value,
|
||||
sentinel_mismatch,
|
||||
unwrap_error,
|
||||
index_out_of_bounds,
|
||||
start_index_greater_than_end,
|
||||
};
|
||||
|
||||
fn addSafetyCheck(
|
||||
@ -22152,12 +22162,7 @@ fn addSafetyCheck(
|
||||
|
||||
defer fail_block.instructions.deinit(gpa);
|
||||
|
||||
// This function doesn't actually need a src location but if
|
||||
// the panic function interface ever changes passing `.unneeded` here
|
||||
// will cause confusing panics.
|
||||
const src = sema.src;
|
||||
_ = try sema.safetyPanic(&fail_block, src, panic_id);
|
||||
|
||||
try sema.safetyPanic(&fail_block, panic_id);
|
||||
try sema.addSafetyCheckExtra(parent_block, ok, &fail_block);
|
||||
}
|
||||
|
||||
@ -22221,7 +22226,7 @@ fn panicWithMsg(
|
||||
block: *Block,
|
||||
src: LazySrcLoc,
|
||||
msg_inst: Air.Inst.Ref,
|
||||
) !Zir.Inst.Index {
|
||||
) !void {
|
||||
const mod = sema.mod;
|
||||
const arena = sema.arena;
|
||||
|
||||
@ -22232,7 +22237,7 @@ fn panicWithMsg(
|
||||
// TODO implement this feature in all the backends and then delete this branch
|
||||
_ = try block.addNoOp(.breakpoint);
|
||||
_ = try block.addNoOp(.unreach);
|
||||
return always_noreturn;
|
||||
return;
|
||||
}
|
||||
const panic_fn = try sema.getBuiltin("panic");
|
||||
const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace");
|
||||
@ -22248,19 +22253,20 @@ fn panicWithMsg(
|
||||
);
|
||||
const args: [3]Air.Inst.Ref = .{ msg_inst, null_stack_trace, .null_value };
|
||||
_ = try sema.analyzeCall(block, panic_fn, src, src, .auto, false, &args, null);
|
||||
return always_noreturn;
|
||||
}
|
||||
|
||||
fn panicUnwrapError(
|
||||
sema: *Sema,
|
||||
parent_block: *Block,
|
||||
src: LazySrcLoc,
|
||||
operand: Air.Inst.Ref,
|
||||
unwrap_err_tag: Air.Inst.Tag,
|
||||
is_non_err_tag: Air.Inst.Tag,
|
||||
) !void {
|
||||
assert(!parent_block.is_comptime);
|
||||
const ok = try parent_block.addUnOp(is_non_err_tag, operand);
|
||||
if (!sema.mod.comp.formatted_panics) {
|
||||
return sema.addSafetyCheck(parent_block, ok, .unwrap_error);
|
||||
}
|
||||
const gpa = sema.gpa;
|
||||
|
||||
var fail_block: Block = .{
|
||||
@ -22289,7 +22295,7 @@ fn panicUnwrapError(
|
||||
const err = try fail_block.addTyOp(unwrap_err_tag, Type.anyerror, operand);
|
||||
const err_return_trace = try sema.getErrorReturnTrace(&fail_block);
|
||||
const args: [2]Air.Inst.Ref = .{ err_return_trace, err };
|
||||
_ = try sema.analyzeCall(&fail_block, panic_fn, src, src, .auto, false, &args, null);
|
||||
_ = try sema.analyzeCall(&fail_block, panic_fn, sema.src, sema.src, .auto, false, &args, null);
|
||||
}
|
||||
}
|
||||
try sema.addSafetyCheckExtra(parent_block, ok, &fail_block);
|
||||
@ -22304,7 +22310,10 @@ fn panicIndexOutOfBounds(
|
||||
) !void {
|
||||
assert(!parent_block.is_comptime);
|
||||
const ok = try parent_block.addBinOp(cmp_op, index, len);
|
||||
try sema.safetyPanicFormatted(parent_block, ok, "panicOutOfBounds", &.{ index, len });
|
||||
if (!sema.mod.comp.formatted_panics) {
|
||||
return sema.addSafetyCheck(parent_block, ok, .index_out_of_bounds);
|
||||
}
|
||||
try sema.safetyCheckFormatted(parent_block, ok, "panicOutOfBounds", &.{ index, len });
|
||||
}
|
||||
|
||||
fn panicStartLargerThanEnd(
|
||||
@ -22315,7 +22324,10 @@ fn panicStartLargerThanEnd(
|
||||
) !void {
|
||||
assert(!parent_block.is_comptime);
|
||||
const ok = try parent_block.addBinOp(.cmp_lte, start, end);
|
||||
try sema.safetyPanicFormatted(parent_block, ok, "panicStartGreaterThanEnd", &.{ start, end });
|
||||
if (!sema.mod.comp.formatted_panics) {
|
||||
return sema.addSafetyCheck(parent_block, ok, .start_index_greater_than_end);
|
||||
}
|
||||
try sema.safetyCheckFormatted(parent_block, ok, "panicStartGreaterThanEnd", &.{ start, end });
|
||||
}
|
||||
|
||||
fn panicInactiveUnionField(
|
||||
@ -22326,7 +22338,10 @@ fn panicInactiveUnionField(
|
||||
) !void {
|
||||
assert(!parent_block.is_comptime);
|
||||
const ok = try parent_block.addBinOp(.cmp_eq, active_tag, wanted_tag);
|
||||
try sema.safetyPanicFormatted(parent_block, ok, "panicInactiveUnionField", &.{ active_tag, wanted_tag });
|
||||
if (!sema.mod.comp.formatted_panics) {
|
||||
return sema.addSafetyCheck(parent_block, ok, .inactive_union_field);
|
||||
}
|
||||
try sema.safetyCheckFormatted(parent_block, ok, "panicInactiveUnionField", &.{ active_tag, wanted_tag });
|
||||
}
|
||||
|
||||
fn panicSentinelMismatch(
|
||||
@ -22369,16 +22384,20 @@ fn panicSentinelMismatch(
|
||||
return;
|
||||
};
|
||||
|
||||
try sema.safetyPanicFormatted(parent_block, ok, "panicSentinelMismatch", &.{ expected_sentinel, actual_sentinel });
|
||||
if (!sema.mod.comp.formatted_panics) {
|
||||
return sema.addSafetyCheck(parent_block, ok, .sentinel_mismatch);
|
||||
}
|
||||
try sema.safetyCheckFormatted(parent_block, ok, "panicSentinelMismatch", &.{ expected_sentinel, actual_sentinel });
|
||||
}
|
||||
|
||||
fn safetyPanicFormatted(
|
||||
fn safetyCheckFormatted(
|
||||
sema: *Sema,
|
||||
parent_block: *Block,
|
||||
ok: Air.Inst.Ref,
|
||||
func: []const u8,
|
||||
args: []const Air.Inst.Ref,
|
||||
) CompileError!void {
|
||||
assert(sema.mod.comp.formatted_panics);
|
||||
const gpa = sema.gpa;
|
||||
|
||||
var fail_block: Block = .{
|
||||
@ -22413,19 +22432,18 @@ fn safetyPanicFormatted(
|
||||
fn safetyPanic(
|
||||
sema: *Sema,
|
||||
block: *Block,
|
||||
src: LazySrcLoc,
|
||||
panic_id: PanicId,
|
||||
) CompileError!Zir.Inst.Index {
|
||||
) CompileError!void {
|
||||
const panic_messages_ty = try sema.getBuiltinType("panic_messages");
|
||||
const msg_decl_index = (try sema.namespaceLookup(
|
||||
block,
|
||||
src,
|
||||
sema.src,
|
||||
panic_messages_ty.getNamespace().?,
|
||||
@tagName(panic_id),
|
||||
)).?;
|
||||
|
||||
const msg_inst = try sema.analyzeDeclVal(block, src, msg_decl_index);
|
||||
return sema.panicWithMsg(block, src, msg_inst);
|
||||
const msg_inst = try sema.analyzeDeclVal(block, sema.src, msg_decl_index);
|
||||
try sema.panicWithMsg(block, sema.src, msg_inst);
|
||||
}
|
||||
|
||||
fn emitBackwardBranch(sema: *Sema, block: *Block, src: LazySrcLoc) !void {
|
||||
|
@ -406,6 +406,8 @@ const usage_build_generic =
|
||||
\\ -fno-function-sections All functions go into same section
|
||||
\\ -fstrip Omit debug symbols
|
||||
\\ -fno-strip Keep debug symbols
|
||||
\\ -fformatted-panics Enable formatted safety panics
|
||||
\\ -fno-formatted-panics Disable formatted safety panics
|
||||
\\ -ofmt=[mode] Override target object format
|
||||
\\ elf Executable and Linking Format
|
||||
\\ c C source code
|
||||
@ -632,6 +634,7 @@ fn buildOutputType(
|
||||
var have_version = false;
|
||||
var compatibility_version: ?std.builtin.Version = null;
|
||||
var strip: ?bool = null;
|
||||
var formatted_panics: ?bool = null;
|
||||
var function_sections = false;
|
||||
var no_builtin = false;
|
||||
var watch = false;
|
||||
@ -1242,6 +1245,10 @@ fn buildOutputType(
|
||||
strip = true;
|
||||
} else if (mem.eql(u8, arg, "-fno-strip")) {
|
||||
strip = false;
|
||||
} else if (mem.eql(u8, arg, "-fformatted-panics")) {
|
||||
formatted_panics = true;
|
||||
} else if (mem.eql(u8, arg, "-fno-formatted-panics")) {
|
||||
formatted_panics = false;
|
||||
} else if (mem.eql(u8, arg, "-fsingle-threaded")) {
|
||||
single_threaded = true;
|
||||
} else if (mem.eql(u8, arg, "-fno-single-threaded")) {
|
||||
@ -2938,6 +2945,7 @@ fn buildOutputType(
|
||||
.stack_size_override = stack_size_override,
|
||||
.image_base_override = image_base_override,
|
||||
.strip = strip,
|
||||
.formatted_panics = formatted_panics,
|
||||
.single_threaded = single_threaded,
|
||||
.function_sections = function_sections,
|
||||
.no_builtin = no_builtin,
|
||||
|
Loading…
Reference in New Issue
Block a user