aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2022-03-19 14:32:09 -0400
committerGitHub <noreply@github.com>2022-03-19 14:32:09 -0400
commit69e6d455ce8e21835ec3ce268a0533e0e7666e8b (patch)
tree8bdc050b60371970ddc8c1d1263a3688e79456aa /src
parentc6cf40a0c03822cac3112be58c61ca55d436b5d0 (diff)
parent12f3c461a4429d9c7a0ddbaa6465bf0499a99b8c (diff)
downloadzig-69e6d455ce8e21835ec3ce268a0533e0e7666e8b.tar.gz
zig-69e6d455ce8e21835ec3ce268a0533e0e7666e8b.zip
Merge pull request #11228 from Vexu/panic
enable default panic handler for stage2 LLVM
Diffstat (limited to 'src')
-rw-r--r--src/Sema.zig117
-rw-r--r--src/link/MachO.zig5
-rw-r--r--src/link/MachO/DebugSymbols.zig1
-rw-r--r--src/value.zig32
4 files changed, 120 insertions, 35 deletions
diff --git a/src/Sema.zig b/src/Sema.zig
index b798405d80..94db6e80b9 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -131,6 +131,9 @@ pub const Block = struct {
c_import_buf: ?*std.ArrayList(u8) = null,
+ /// type of `err` in `else => |err|`
+ switch_else_err_ty: ?Type = null,
+
const Param = struct {
/// `noreturn` means `anytype`.
ty: Type,
@@ -189,6 +192,7 @@ pub const Block = struct {
.runtime_index = parent.runtime_index,
.want_safety = parent.want_safety,
.c_import_buf = parent.c_import_buf,
+ .switch_else_err_ty = parent.switch_else_err_ty,
};
}
@@ -3930,6 +3934,23 @@ fn analyzeBlockBody(
// to emit a jump instruction to after the block when it encounters the break.
try parent_block.instructions.append(gpa, merges.block_inst);
const resolved_ty = try sema.resolvePeerTypes(parent_block, src, merges.results.items, .none);
+
+ const type_src = src; // TODO: better source location
+ const valid_rt = try sema.validateRunTimeType(child_block, type_src, resolved_ty, false);
+ if (!valid_rt) {
+ const msg = msg: {
+ const msg = try sema.errMsg(child_block, type_src, "value with comptime only type '{}' depends on runtime control flow", .{resolved_ty});
+ errdefer msg.destroy(sema.gpa);
+
+ const runtime_src = child_block.runtime_cond orelse child_block.runtime_loop.?;
+ try sema.errNote(child_block, runtime_src, msg, "runtime control flow here", .{});
+
+ try sema.explainWhyTypeIsComptime(child_block, type_src, msg, type_src.toSrcLoc(child_block.src_decl), resolved_ty);
+
+ break :msg msg;
+ };
+ return sema.failWithOwnedErrorMsg(child_block, msg);
+ }
const ty_inst = try sema.addType(resolved_ty);
try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Block).Struct.fields.len +
child_block.instructions.items.len);
@@ -4191,6 +4212,11 @@ fn zirBreak(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) CompileError
const br_ref = try start_block.addBr(label.merges.block_inst, operand);
try label.merges.results.append(sema.gpa, operand);
try label.merges.br_list.append(sema.gpa, Air.refToIndex(br_ref).?);
+ block.runtime_index += 1;
+ if (block.runtime_cond == null and block.runtime_loop == null) {
+ block.runtime_cond = start_block.runtime_cond orelse start_block.runtime_loop;
+ block.runtime_loop = start_block.runtime_loop;
+ }
return inst;
}
}
@@ -6692,12 +6718,6 @@ fn zirSwitchCapture(
if (capture_info.prong_index == std.math.maxInt(@TypeOf(capture_info.prong_index))) {
// It is the else/`_` prong.
- switch (operand_ty.zigTypeTag()) {
- .ErrorSet => {
- return sema.fail(block, operand_src, "TODO implement Sema for zirSwitchCaptureElse for error sets", .{});
- },
- else => {},
- }
if (is_ref) {
assert(operand_is_ref);
return operand_ptr;
@@ -6708,7 +6728,10 @@ fn zirSwitchCapture(
else
operand_ptr;
- return operand;
+ switch (operand_ty.zigTypeTag()) {
+ .ErrorSet => return sema.bitCast(block, block.switch_else_err_ty.?, operand, operand_src),
+ else => return operand,
+ }
}
if (is_multi) {
@@ -6885,6 +6908,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
const operand_ty = sema.typeOf(operand);
+ var else_error_ty: ?Type = null;
+
// Validate usage of '_' prongs.
if (special_prong == .under and !operand_ty.isNonexhaustiveEnum()) {
const msg = msg: {
@@ -7077,6 +7102,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
.{},
);
}
+ else_error_ty = Type.@"anyerror";
} else {
var maybe_msg: ?*Module.ErrorMsg = null;
errdefer if (maybe_msg) |msg| msg.destroy(sema.gpa);
@@ -7121,6 +7147,17 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
.{},
);
}
+
+ const error_names = operand_ty.errorSetNames();
+ var names: Module.ErrorSet.NameMap = .{};
+ try names.ensureUnusedCapacity(sema.arena, error_names.len);
+ for (error_names) |error_name| {
+ if (seen_errors.contains(error_name)) continue;
+
+ names.putAssumeCapacityNoClobber(error_name, {});
+ }
+
+ else_error_ty = try Type.Tag.error_set_merged.create(sema.arena, names);
}
},
.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
.label = &label,
.inlining = block.inlining,
.is_comptime = block.is_comptime,
+ .switch_else_err_ty = else_error_ty,
};
const merges = &child_block.label.?.merges;
defer child_block.instructions.deinit(gpa);
@@ -15447,6 +15485,26 @@ fn validateVarType(
var_ty: Type,
is_extern: bool,
) CompileError!void {
+ if (try sema.validateRunTimeType(block, src, var_ty, is_extern)) return;
+
+ const msg = msg: {
+ const msg = try sema.errMsg(block, src, "variable of type '{}' must be const or comptime", .{var_ty});
+ errdefer msg.destroy(sema.gpa);
+
+ try sema.explainWhyTypeIsComptime(block, src, msg, src.toSrcLoc(block.src_decl), var_ty);
+
+ break :msg msg;
+ };
+ return sema.failWithOwnedErrorMsg(block, msg);
+}
+
+fn validateRunTimeType(
+ sema: *Sema,
+ block: *Block,
+ src: LazySrcLoc,
+ var_ty: Type,
+ is_extern: bool,
+) CompileError!bool {
var ty = var_ty;
while (true) switch (ty.zigTypeTag()) {
.Bool,
@@ -15457,7 +15515,7 @@ fn validateVarType(
.Frame,
.AnyFrame,
.Void,
- => return,
+ => return true,
.BoundFn,
.ComptimeFloat,
@@ -15468,21 +15526,21 @@ fn validateVarType(
.Undefined,
.Null,
.Fn,
- => break,
+ => return false,
.Pointer => {
const elem_ty = ty.childType();
switch (elem_ty.zigTypeTag()) {
- .Opaque, .Fn => return,
+ .Opaque, .Fn => return true,
else => ty = elem_ty,
}
},
- .Opaque => if (is_extern) return else break,
+ .Opaque => return is_extern,
.Optional => {
var buf: Type.Payload.ElemType = undefined;
const child_ty = ty.optionalChild(&buf);
- return validateVarType(sema, block, src, child_ty, is_extern);
+ return validateRunTimeType(sema, block, src, child_ty, is_extern);
},
.Array, .Vector => ty = ty.elemType(),
@@ -15490,23 +15548,10 @@ fn validateVarType(
.Struct, .Union => {
const resolved_ty = try sema.resolveTypeFields(block, src, ty);
- if (try sema.typeRequiresComptime(block, src, resolved_ty)) {
- break;
- } else {
- return;
- }
+ const needs_comptime = try sema.typeRequiresComptime(block, src, resolved_ty);
+ return !needs_comptime;
},
- } else unreachable; // TODO should not need else unreachable
-
- const msg = msg: {
- const msg = try sema.errMsg(block, src, "variable of type '{}' must be const or comptime", .{var_ty});
- errdefer msg.destroy(sema.gpa);
-
- try sema.explainWhyTypeIsComptime(block, src, msg, src.toSrcLoc(block.src_decl), var_ty);
-
- break :msg msg;
};
- return sema.failWithOwnedErrorMsg(block, msg);
}
fn explainWhyTypeIsComptime(
@@ -18494,8 +18539,8 @@ pub fn bitCastVal(
const abi_size = try sema.usizeCast(block, src, old_ty.abiSize(target));
const buffer = try sema.gpa.alloc(u8, abi_size);
defer sema.gpa.free(buffer);
- val.writeToMemory(old_ty, target, buffer);
- return Value.readFromMemory(new_ty, target, buffer[buffer_offset..], sema.arena);
+ val.writeToMemory(old_ty, sema.mod, buffer);
+ return Value.readFromMemory(new_ty, sema.mod, buffer[buffer_offset..], sema.arena);
}
fn coerceArrayPtrToSlice(
@@ -20351,6 +20396,20 @@ pub fn resolveTypeFully(
return resolveTypeFully(sema, block, src, ty.optionalChild(&buf));
},
.ErrorUnion => return resolveTypeFully(sema, block, src, ty.errorUnionPayload()),
+ .Fn => {
+ const info = ty.fnInfo();
+ if (info.is_generic) {
+ // Resolving of generic function types is defeerred to when
+ // the function is instantiated.
+ return;
+ }
+ for (info.param_types) |param_ty| {
+ const param_ty_src = src; // TODO better source location
+ try sema.resolveTypeFully(block, param_ty_src, param_ty);
+ }
+ const return_ty_src = src; // TODO better source location
+ try sema.resolveTypeFully(block, return_ty_src, info.return_type);
+ },
else => {},
}
}
diff --git a/src/link/MachO.zig b/src/link/MachO.zig
index 694ddc5613..1cab5fe067 100644
--- a/src/link/MachO.zig
+++ b/src/link/MachO.zig
@@ -4301,6 +4301,7 @@ fn populateMissingMetadata(self: *MachO) !void {
.inner = .{
.segname = makeStaticString("__PAGEZERO"),
.vmsize = pagezero_vmsize,
+ .cmdsize = @sizeOf(macho.segment_command_64),
},
},
});
@@ -4326,6 +4327,7 @@ fn populateMissingMetadata(self: *MachO) !void {
.filesize = needed_size,
.maxprot = macho.PROT.READ | macho.PROT.EXEC,
.initprot = macho.PROT.READ | macho.PROT.EXEC,
+ .cmdsize = @sizeOf(macho.segment_command_64),
},
},
});
@@ -4431,6 +4433,7 @@ fn populateMissingMetadata(self: *MachO) !void {
.filesize = needed_size,
.maxprot = macho.PROT.READ | macho.PROT.WRITE,
.initprot = macho.PROT.READ | macho.PROT.WRITE,
+ .cmdsize = @sizeOf(macho.segment_command_64),
},
},
});
@@ -4480,6 +4483,7 @@ fn populateMissingMetadata(self: *MachO) !void {
.filesize = needed_size,
.maxprot = macho.PROT.READ | macho.PROT.WRITE,
.initprot = macho.PROT.READ | macho.PROT.WRITE,
+ .cmdsize = @sizeOf(macho.segment_command_64),
},
},
});
@@ -4589,6 +4593,7 @@ fn populateMissingMetadata(self: *MachO) !void {
.fileoff = fileoff,
.maxprot = macho.PROT.READ,
.initprot = macho.PROT.READ,
+ .cmdsize = @sizeOf(macho.segment_command_64),
},
},
});
diff --git a/src/link/MachO/DebugSymbols.zig b/src/link/MachO/DebugSymbols.zig
index 3d80e9a9b5..9fc2828ea1 100644
--- a/src/link/MachO/DebugSymbols.zig
+++ b/src/link/MachO/DebugSymbols.zig
@@ -148,6 +148,7 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: Allocator) !void
.vmsize = needed_size,
.fileoff = fileoff,
.filesize = needed_size,
+ .cmdsize = @sizeOf(macho.segment_command_64),
},
},
});
diff --git a/src/value.zig b/src/value.zig
index b45c106c26..8e6afccb60 100644
--- a/src/value.zig
+++ b/src/value.zig
@@ -1042,7 +1042,8 @@ pub const Value = extern union {
};
}
- pub fn writeToMemory(val: Value, ty: Type, target: Target, buffer: []u8) void {
+ pub fn writeToMemory(val: Value, ty: Type, mod: *Module, buffer: []u8) void {
+ const target = mod.getTarget();
if (val.isUndef()) {
const size = @intCast(usize, ty.abiSize(target));
std.mem.set(u8, buffer[0..size], 0xaa);
@@ -1081,7 +1082,7 @@ pub const Value = extern union {
var buf_off: usize = 0;
while (elem_i < len) : (elem_i += 1) {
const elem_val = val.elemValueBuffer(elem_i, &elem_value_buf);
- writeToMemory(elem_val, elem_ty, target, buffer[buf_off..]);
+ writeToMemory(elem_val, elem_ty, mod, buffer[buf_off..]);
buf_off += elem_size;
}
},
@@ -1092,7 +1093,7 @@ pub const Value = extern union {
const field_vals = val.castTag(.aggregate).?.data;
for (fields) |field, i| {
const off = @intCast(usize, ty.structFieldOffset(i, target));
- writeToMemory(field_vals[i], field.ty, target, buffer[off..]);
+ writeToMemory(field_vals[i], field.ty, mod, buffer[off..]);
}
},
.Packed => {
@@ -1105,6 +1106,12 @@ pub const Value = extern union {
host_int.writeTwosComplement(buffer, bit_size, abi_size, target.cpu.arch.endian());
},
},
+ .ErrorSet => {
+ // TODO revisit this when we have the concept of the error tag type
+ const Int = u16;
+ const int = mod.global_error_set.get(val.castTag(.@"error").?.data.name).?;
+ std.mem.writeInt(Int, buffer[0..@sizeOf(Int)], @intCast(Int, int), target.cpu.arch.endian());
+ },
else => @panic("TODO implement writeToMemory for more types"),
}
}
@@ -1153,10 +1160,11 @@ pub const Value = extern union {
pub fn readFromMemory(
ty: Type,
- target: Target,
+ mod: *Module,
buffer: []const u8,
arena: Allocator,
) Allocator.Error!Value {
+ const target = mod.getTarget();
switch (ty.zigTypeTag()) {
.Int => {
if (buffer.len == 0) return Value.zero;
@@ -1184,7 +1192,7 @@ pub const Value = extern union {
const elems = try arena.alloc(Value, @intCast(usize, ty.arrayLen()));
var offset: usize = 0;
for (elems) |*elem| {
- elem.* = try readFromMemory(elem_ty, target, buffer[offset..], arena);
+ elem.* = try readFromMemory(elem_ty, mod, buffer[offset..], arena);
offset += @intCast(usize, elem_size);
}
return Tag.aggregate.create(arena, elems);
@@ -1196,7 +1204,7 @@ pub const Value = extern union {
const field_vals = try arena.alloc(Value, fields.len);
for (fields) |field, i| {
const off = @intCast(usize, ty.structFieldOffset(i, target));
- field_vals[i] = try readFromMemory(field.ty, target, buffer[off..], arena);
+ field_vals[i] = try readFromMemory(field.ty, mod, buffer[off..], arena);
}
return Tag.aggregate.create(arena, field_vals);
},
@@ -1212,6 +1220,18 @@ pub const Value = extern union {
return intToPackedStruct(ty, target, bigint.toConst(), arena);
},
},
+ .ErrorSet => {
+ // TODO revisit this when we have the concept of the error tag type
+ const Int = u16;
+ const int = std.mem.readInt(Int, buffer[0..@sizeOf(Int)], target.cpu.arch.endian());
+
+ const payload = try arena.create(Value.Payload.Error);
+ payload.* = .{
+ .base = .{ .tag = .@"error" },
+ .data = .{ .name = mod.error_name_list.items[@intCast(usize, int)] },
+ };
+ return Value.initPayload(&payload.base);
+ },
else => @panic("TODO implement readFromMemory for more types"),
}
}