mirror of
https://github.com/ziglang/zig.git
synced 2024-12-17 00:30:15 +00:00
reimplement integer overflow safety panic function calls
in the llvm backend.
This commit is contained in:
parent
f2c8940aa6
commit
b66cc5af41
43
src/Sema.zig
43
src/Sema.zig
@ -5703,27 +5703,7 @@ fn addStrLit(sema: *Sema, string: InternPool.String, len: u64) CompileError!Air.
|
||||
}
|
||||
|
||||
fn uavRef(sema: *Sema, val: InternPool.Index) CompileError!Air.Inst.Ref {
|
||||
return Air.internedToRef(try sema.refValue(val));
|
||||
}
|
||||
|
||||
fn refValue(sema: *Sema, val: InternPool.Index) CompileError!InternPool.Index {
|
||||
const pt = sema.pt;
|
||||
const ptr_ty = (try pt.ptrTypeSema(.{
|
||||
.child = pt.zcu.intern_pool.typeOf(val),
|
||||
.flags = .{
|
||||
.alignment = .none,
|
||||
.is_const = true,
|
||||
.address_space = .generic,
|
||||
},
|
||||
})).toIntern();
|
||||
return pt.intern(.{ .ptr = .{
|
||||
.ty = ptr_ty,
|
||||
.base_addr = .{ .uav = .{
|
||||
.val = val,
|
||||
.orig_ty = ptr_ty,
|
||||
} },
|
||||
.byte_offset = 0,
|
||||
} });
|
||||
return Air.internedToRef(try sema.pt.refValue(val));
|
||||
}
|
||||
|
||||
fn zirInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
|
||||
@ -17402,6 +17382,7 @@ fn analyzeArithmetic(
|
||||
|
||||
if (block.wantSafety() and want_safety and scalar_tag == .int) {
|
||||
if (zcu.backendSupportsFeature(.safety_checked_instructions)) {
|
||||
if (air_tag != air_tag_safe) try sema.preparePanicIntegerOverflow(block, src);
|
||||
return block.addBinOp(air_tag_safe, casted_lhs, casted_rhs);
|
||||
} else {
|
||||
const maybe_op_ov: ?Air.Inst.Tag = switch (air_tag) {
|
||||
@ -27706,6 +27687,24 @@ fn preparePanic(sema: *Sema, block: *Block, src: LazySrcLoc) !void {
|
||||
const panic_cause_ty = try pt.getBuiltinType("PanicCause");
|
||||
try panic_cause_ty.resolveFields(pt);
|
||||
zcu.panic_cause_type = panic_cause_ty.toIntern();
|
||||
zcu.panic_cause_tag_type = panic_cause_ty.unionTagType(zcu).?.toIntern();
|
||||
}
|
||||
}
|
||||
|
||||
fn preparePanicIntegerOverflow(sema: *Sema, block: *Block, src: LazySrcLoc) !void {
|
||||
const pt = sema.pt;
|
||||
const zcu = pt.zcu;
|
||||
try preparePanic(sema, block, src);
|
||||
if (zcu.panic_cause_integer_overflow == .none) {
|
||||
const union_val = try pt.unionValue(
|
||||
Type.fromInterned(zcu.panic_cause_type),
|
||||
try pt.enumValueFieldIndex(
|
||||
Type.fromInterned(zcu.panic_cause_tag_type),
|
||||
@intFromEnum(PanicCauseTag.integer_overflow),
|
||||
),
|
||||
Value.void,
|
||||
);
|
||||
zcu.panic_cause_integer_overflow = try pt.refValue(union_val.toIntern());
|
||||
}
|
||||
}
|
||||
|
||||
@ -32669,7 +32668,7 @@ fn optRefValue(sema: *Sema, opt_val: ?Value) !Value {
|
||||
return Value.fromInterned(try pt.intern(.{ .opt = .{
|
||||
.ty = (try pt.optionalType(ptr_anyopaque_ty.toIntern())).toIntern(),
|
||||
.val = if (opt_val) |val| (try pt.getCoerced(
|
||||
Value.fromInterned(try sema.refValue(val.toIntern())),
|
||||
Value.fromInterned(try pt.refValue(val.toIntern())),
|
||||
ptr_anyopaque_ty,
|
||||
)).toIntern() else .none,
|
||||
} }));
|
||||
|
@ -214,6 +214,8 @@ free_type_references: std.ArrayListUnmanaged(u32) = .empty,
|
||||
panic_func_index: InternPool.Index = .none,
|
||||
null_stack_trace: InternPool.Index = .none,
|
||||
panic_cause_type: InternPool.Index = .none,
|
||||
panic_cause_tag_type: InternPool.Index = .none,
|
||||
panic_cause_integer_overflow: InternPool.Index = .none,
|
||||
|
||||
generation: u32 = 0,
|
||||
|
||||
|
@ -3656,6 +3656,25 @@ pub fn ensureNamespaceUpToDate(pt: Zcu.PerThread, namespace_index: Zcu.Namespace
|
||||
namespace.generation = zcu.generation;
|
||||
}
|
||||
|
||||
pub fn refValue(pt: Zcu.PerThread, val: InternPool.Index) Zcu.SemaError!InternPool.Index {
|
||||
const ptr_ty = (try pt.ptrTypeSema(.{
|
||||
.child = pt.zcu.intern_pool.typeOf(val),
|
||||
.flags = .{
|
||||
.alignment = .none,
|
||||
.is_const = true,
|
||||
.address_space = .generic,
|
||||
},
|
||||
})).toIntern();
|
||||
return pt.intern(.{ .ptr = .{
|
||||
.ty = ptr_ty,
|
||||
.base_addr = .{ .uav = .{
|
||||
.val = val,
|
||||
.orig_ty = ptr_ty,
|
||||
} },
|
||||
.byte_offset = 0,
|
||||
} });
|
||||
}
|
||||
|
||||
const Air = @import("../Air.zig");
|
||||
const Allocator = std.mem.Allocator;
|
||||
const assert = std.debug.assert;
|
||||
|
@ -5677,46 +5677,37 @@ pub const FuncGen = struct {
|
||||
|
||||
const PanicCauseTag = @typeInfo(std.builtin.PanicCause).@"union".tag_type.?;
|
||||
|
||||
fn buildSimplePanic(fg: *FuncGen, panic_cause_tag: PanicCauseTag) !void {
|
||||
// TODO update this before merging the branch
|
||||
_ = panic_cause_tag;
|
||||
//const o = fg.ng.object;
|
||||
//const zcu = o.pt.zcu;
|
||||
//const ip = &zcu.intern_pool;
|
||||
//const msg_nav_index = zcu.panic_messages[@intFromEnum(panic_id)].unwrap().?;
|
||||
//const msg_nav = ip.getNav(msg_nav_index);
|
||||
//const msg_len = Type.fromInterned(msg_nav.typeOf(ip)).childType(zcu).arrayLen(zcu);
|
||||
//const msg_ptr = try o.lowerValue(msg_nav.status.resolved.val);
|
||||
//const null_opt_addr_global = try fg.resolveNullOptUsize();
|
||||
//const target = zcu.getTarget();
|
||||
//const llvm_usize = try o.lowerType(Type.usize);
|
||||
//// example:
|
||||
//// call fastcc void @test2.panic(
|
||||
//// ptr @builtin.panic_messages.integer_overflow__anon_987, ; msg.ptr
|
||||
//// i64 16, ; msg.len
|
||||
//// ptr null, ; stack trace
|
||||
//// ptr @2, ; addr (null ?usize)
|
||||
//// )
|
||||
//const panic_func = zcu.funcInfo(zcu.panic_func_index);
|
||||
//const panic_nav = ip.getNav(panic_func.owner_nav);
|
||||
//const fn_info = zcu.typeToFunc(Type.fromInterned(panic_nav.typeOf(ip))).?;
|
||||
//const panic_global = try o.resolveLlvmFunction(panic_func.owner_nav);
|
||||
//_ = try fg.wip.callIntrinsicAssumeCold();
|
||||
//_ = try fg.wip.call(
|
||||
// .normal,
|
||||
// toLlvmCallConv(fn_info.cc, target),
|
||||
// .none,
|
||||
// panic_global.typeOf(&o.builder),
|
||||
// panic_global.toValue(&o.builder),
|
||||
// &.{
|
||||
// msg_ptr.toValue(),
|
||||
// try o.builder.intValue(llvm_usize, msg_len),
|
||||
// try o.builder.nullValue(.ptr),
|
||||
// null_opt_addr_global.toValue(),
|
||||
// },
|
||||
// "",
|
||||
//);
|
||||
_ = try fg.wip.callIntrinsic(.normal, .none, .trap, &.{}, &.{}, "");
|
||||
fn buildSimplePanic(fg: *FuncGen, panic_cause: InternPool.Index) !void {
|
||||
const o = fg.ng.object;
|
||||
const zcu = o.pt.zcu;
|
||||
const ip = &zcu.intern_pool;
|
||||
const cause_ptr = try o.lowerValue(panic_cause);
|
||||
const null_opt_addr_global = try fg.resolveNullOptUsize();
|
||||
const target = zcu.getTarget();
|
||||
// example:
|
||||
// call fastcc void @test2.panic(
|
||||
// ptr @foo, ; panic_cause
|
||||
// ptr null, ; stack trace
|
||||
// ptr @2, ; addr (null ?usize)
|
||||
// )
|
||||
const panic_func = zcu.funcInfo(zcu.panic_func_index);
|
||||
const panic_nav = ip.getNav(panic_func.owner_nav);
|
||||
const fn_info = zcu.typeToFunc(Type.fromInterned(panic_nav.typeOf(ip))).?;
|
||||
const panic_global = try o.resolveLlvmFunction(panic_func.owner_nav);
|
||||
_ = try fg.wip.callIntrinsicAssumeCold();
|
||||
_ = try fg.wip.call(
|
||||
.normal,
|
||||
toLlvmCallConv(fn_info.cc, target),
|
||||
.none,
|
||||
panic_global.typeOf(&o.builder),
|
||||
panic_global.toValue(&o.builder),
|
||||
&.{
|
||||
cause_ptr.toValue(),
|
||||
try o.builder.nullValue(.ptr),
|
||||
null_opt_addr_global.toValue(),
|
||||
},
|
||||
"",
|
||||
);
|
||||
_ = try fg.wip.@"unreachable"();
|
||||
}
|
||||
|
||||
@ -8340,7 +8331,7 @@ pub const FuncGen = struct {
|
||||
_ = try fg.wip.brCond(overflow_bit, fail_block, ok_block, .none);
|
||||
|
||||
fg.wip.cursor = .{ .block = fail_block };
|
||||
try fg.buildSimplePanic(.integer_overflow);
|
||||
try fg.buildSimplePanic(zcu.panic_cause_integer_overflow);
|
||||
|
||||
fg.wip.cursor = .{ .block = ok_block };
|
||||
return fg.wip.extractValue(results, &.{0}, "");
|
||||
|
Loading…
Reference in New Issue
Block a user