Merge pull request #13806 from Vexu/stage2-fixes

misc fixes and improvements
This commit is contained in:
Andrew Kelley 2022-12-07 21:35:02 -05:00 committed by GitHub
commit d69e97ae16
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 120 additions and 194 deletions

View File

@ -3,7 +3,9 @@ const divc3 = @import("./divc3.zig");
const Complex = @import("./mulc3.zig").Complex;
comptime {
@export(__divdc3, .{ .name = "__divdc3", .linkage = common.linkage });
if (@import("builtin").zig_backend != .stage2_c) {
@export(__divdc3, .{ .name = "__divdc3", .linkage = common.linkage });
}
}
pub fn __divdc3(a: f64, b: f64, c: f64, d: f64) callconv(.C) Complex(f64) {

View File

@ -3,7 +3,9 @@ const divc3 = @import("./divc3.zig");
const Complex = @import("./mulc3.zig").Complex;
comptime {
@export(__divhc3, .{ .name = "__divhc3", .linkage = common.linkage });
if (@import("builtin").zig_backend != .stage2_c) {
@export(__divhc3, .{ .name = "__divhc3", .linkage = common.linkage });
}
}
pub fn __divhc3(a: f16, b: f16, c: f16, d: f16) callconv(.C) Complex(f16) {

View File

@ -3,7 +3,9 @@ const divc3 = @import("./divc3.zig");
const Complex = @import("./mulc3.zig").Complex;
comptime {
@export(__divsc3, .{ .name = "__divsc3", .linkage = common.linkage });
if (@import("builtin").zig_backend != .stage2_c) {
@export(__divsc3, .{ .name = "__divsc3", .linkage = common.linkage });
}
}
pub fn __divsc3(a: f32, b: f32, c: f32, d: f32) callconv(.C) Complex(f32) {

View File

@ -3,7 +3,9 @@ const divc3 = @import("./divc3.zig");
const Complex = @import("./mulc3.zig").Complex;
comptime {
@export(__divtc3, .{ .name = "__divtc3", .linkage = common.linkage });
if (@import("builtin").zig_backend != .stage2_c) {
@export(__divtc3, .{ .name = "__divtc3", .linkage = common.linkage });
}
}
pub fn __divtc3(a: f128, b: f128, c: f128, d: f128) callconv(.C) Complex(f128) {

View File

@ -3,7 +3,9 @@ const divc3 = @import("./divc3.zig");
const Complex = @import("./mulc3.zig").Complex;
comptime {
@export(__divxc3, .{ .name = "__divxc3", .linkage = common.linkage });
if (@import("builtin").zig_backend != .stage2_c) {
@export(__divxc3, .{ .name = "__divxc3", .linkage = common.linkage });
}
}
pub fn __divxc3(a: f80, b: f80, c: f80, d: f80) callconv(.C) Complex(f80) {

View File

@ -4,7 +4,9 @@ const mulc3 = @import("./mulc3.zig");
pub const panic = common.panic;
comptime {
@export(__muldc3, .{ .name = "__muldc3", .linkage = common.linkage });
if (@import("builtin").zig_backend != .stage2_c) {
@export(__muldc3, .{ .name = "__muldc3", .linkage = common.linkage });
}
}
pub fn __muldc3(a: f64, b: f64, c: f64, d: f64) callconv(.C) mulc3.Complex(f64) {

View File

@ -4,7 +4,9 @@ const mulc3 = @import("./mulc3.zig");
pub const panic = common.panic;
comptime {
@export(__mulhc3, .{ .name = "__mulhc3", .linkage = common.linkage });
if (@import("builtin").zig_backend != .stage2_c) {
@export(__mulhc3, .{ .name = "__mulhc3", .linkage = common.linkage });
}
}
pub fn __mulhc3(a: f16, b: f16, c: f16, d: f16) callconv(.C) mulc3.Complex(f16) {

View File

@ -4,7 +4,9 @@ const mulc3 = @import("./mulc3.zig");
pub const panic = common.panic;
comptime {
@export(__mulsc3, .{ .name = "__mulsc3", .linkage = common.linkage });
if (@import("builtin").zig_backend != .stage2_c) {
@export(__mulsc3, .{ .name = "__mulsc3", .linkage = common.linkage });
}
}
pub fn __mulsc3(a: f32, b: f32, c: f32, d: f32) callconv(.C) mulc3.Complex(f32) {

View File

@ -4,7 +4,9 @@ const mulc3 = @import("./mulc3.zig");
pub const panic = common.panic;
comptime {
@export(__multc3, .{ .name = "__multc3", .linkage = common.linkage });
if (@import("builtin").zig_backend != .stage2_c) {
@export(__multc3, .{ .name = "__multc3", .linkage = common.linkage });
}
}
pub fn __multc3(a: f128, b: f128, c: f128, d: f128) callconv(.C) mulc3.Complex(f128) {

View File

@ -4,7 +4,9 @@ const mulc3 = @import("./mulc3.zig");
pub const panic = common.panic;
comptime {
@export(__mulxc3, .{ .name = "__mulxc3", .linkage = common.linkage });
if (@import("builtin").zig_backend != .stage2_c) {
@export(__mulxc3, .{ .name = "__mulxc3", .linkage = common.linkage });
}
}
pub fn __mulxc3(a: f80, b: f80, c: f80, d: f80) callconv(.C) mulc3.Complex(f80) {

View File

@ -177,7 +177,7 @@ fn printLiteral(out: anytype, val: anytype, indent: u8) !void {
.Float,
.Null,
=> try out.print("{any}", .{val}),
else => @compileError(comptime std.fmt.comptimePrint("`{s}` are not yet supported as build options", .{@tagName(@typeInfo(T))})),
else => @compileError(std.fmt.comptimePrint("`{s}` are not yet supported as build options", .{@tagName(@typeInfo(T))})),
}
}

View File

@ -199,7 +199,7 @@ pub fn format(
switch (missing_count) {
0 => unreachable,
1 => @compileError("unused argument in '" ++ fmt ++ "'"),
else => @compileError((comptime comptimePrint("{d}", .{missing_count})) ++ " unused arguments in '" ++ fmt ++ "'"),
else => @compileError(comptimePrint("{d}", .{missing_count}) ++ " unused arguments in '" ++ fmt ++ "'"),
}
}
}

View File

@ -765,7 +765,7 @@ pub fn checkAllAllocationFailures(backing_allocator: std.mem.Allocator, comptime
}
const expected_args_tuple_len = fn_args_fields.len - 1;
if (extra_args.len != expected_args_tuple_len) {
@compileError("The provided function expects " ++ (comptime std.fmt.comptimePrint("{d}", .{expected_args_tuple_len})) ++ " extra arguments, but the provided tuple contains " ++ (comptime std.fmt.comptimePrint("{d}", .{extra_args.len})));
@compileError("The provided function expects " ++ std.fmt.comptimePrint("{d}", .{expected_args_tuple_len}) ++ " extra arguments, but the provided tuple contains " ++ std.fmt.comptimePrint("{d}", .{extra_args.len}));
}
// Setup the tuple that will actually be used with @call (we'll need to insert

View File

@ -425,7 +425,16 @@ pub const Tokenizer = struct {
const c = self.buffer[self.index];
switch (state) {
.start => switch (c) {
0 => break,
0 => {
if (self.index != self.buffer.len) {
result.tag = .invalid;
result.loc.start = self.index;
self.index += 1;
result.loc.end = self.index;
return result;
}
break;
},
' ', '\n', '\t', '\r' => {
result.loc.start = self.index + 1;
},
@ -1851,6 +1860,13 @@ test "saturating operators" {
try testTokenize("-|=", &.{.minus_pipe_equal});
}
test "null byte before eof" {
try testTokenize("123 \x00 456", &.{ .number_literal, .invalid, .number_literal });
try testTokenize("//\x00", &.{.invalid});
try testTokenize("\\\\\x00", &.{ .multiline_string_literal_line, .invalid });
try testTokenize("\x00", &.{.invalid});
}
fn testTokenize(source: [:0]const u8, expected_token_tags: []const Token.Tag) !void {
var tokenizer = Tokenizer.init(source);
for (expected_token_tags) |expected_token_tag| {

View File

@ -8455,8 +8455,12 @@ fn simpleUnOp(
operand_node: Ast.Node.Index,
tag: Zir.Inst.Tag,
) InnerError!Zir.Inst.Ref {
const prev_force_comptime = gz.force_comptime;
defer gz.force_comptime = prev_force_comptime;
switch (tag) {
.tag_name, .error_name, .ptr_to_int => try emitDbgNode(gz, node),
.compile_error => gz.force_comptime = true,
else => {},
}
const operand = try expr(gz, scope, operand_ri, operand_node);

View File

@ -5405,6 +5405,13 @@ fn zirExport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
},
else => |e| return e,
};
{
try sema.mod.ensureDeclAnalyzed(decl_index);
const exported_decl = sema.mod.declPtr(decl_index);
if (exported_decl.val.castTag(.function)) |some| {
return sema.analyzeExport(block, src, options, some.data.owner_decl);
}
}
try sema.analyzeExport(block, src, options, decl_index);
}
@ -17870,6 +17877,13 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
operand_ty.fmt(mod),
}),
};
if (enum_ty.enumFieldCount() == 0) {
// TODO I don't think this is the correct way to handle this but
// it prevents a crash.
return sema.fail(block, operand_src, "cannot get @tagName of empty enum '{}'", .{
enum_ty.fmt(mod),
});
}
const enum_decl_index = enum_ty.getOwnerDecl();
const casted_operand = try sema.coerce(block, enum_ty, operand, operand_src);
if (try sema.resolveDefinedValue(block, operand_src, casted_operand)) |val| {
@ -20997,6 +21011,9 @@ fn analyzeMinMax(
if (rhs_val.isUndef()) return sema.addConstUndef(simd_op.result_ty);
try sema.resolveLazyValue(lhs_val);
try sema.resolveLazyValue(rhs_val);
const opFunc = switch (air_tag) {
.min => Value.numberMin,
.max => Value.numberMax,

View File

@ -46,6 +46,7 @@ pub fn enumToInt(tv: TypedValue, buffer: *Value.Payload.U64) Value {
}
const max_aggregate_items = 100;
const max_string_len = 256;
const FormatContext = struct {
tv: TypedValue,
@ -141,10 +142,12 @@ pub fn print(
.extern_options_type => return writer.writeAll("std.builtin.ExternOptions"),
.type_info_type => return writer.writeAll("std.builtin.Type"),
.empty_struct_value, .aggregate => {
.empty_struct_value => return writer.writeAll(".{}"),
.aggregate => {
if (level == 0) {
return writer.writeAll(".{ ... }");
}
const values = val.castTag(.aggregate).?;
if (ty.zigTypeTag() == .Struct) {
try writer.writeAll(".{");
const max_len = std.math.min(ty.structFieldCount(), max_aggregate_items);
@ -159,9 +162,9 @@ pub fn print(
try print(.{
.ty = ty.structFieldType(i),
.val = switch (ty.containerLayout()) {
.Packed => val.castTag(.aggregate).?.data[i],
.Packed => values.data[i],
else => ty.structFieldValueComptime(i) orelse b: {
const vals = val.castTag(.aggregate).?.data;
const vals = values.data;
break :b vals[i];
},
},
@ -172,17 +175,31 @@ pub fn print(
}
return writer.writeAll("}");
} else {
try writer.writeAll(".{ ");
const elem_ty = ty.elemType2();
const len = ty.arrayLen();
const max_len = std.math.min(len, max_aggregate_items);
if (elem_ty.eql(Type.u8, mod)) str: {
const max_len = @intCast(usize, std.math.min(len, max_string_len));
var buf: [max_string_len]u8 = undefined;
var i: u32 = 0;
while (i < max_len) : (i += 1) {
buf[i] = std.math.cast(u8, values.data[i].toUnsignedInt(target)) orelse break :str;
}
const truncated = if (len > max_string_len) " (truncated)" else "";
return writer.print("\"{}{s}\"", .{ std.zig.fmtEscapes(buf[0..max_len]), truncated });
}
try writer.writeAll(".{ ");
const max_len = std.math.min(len, max_aggregate_items);
var i: u32 = 0;
while (i < max_len) : (i += 1) {
if (i != 0) try writer.writeAll(", ");
try print(.{
.ty = elem_ty,
.val = val.castTag(.aggregate).?.data[i],
.val = values.data[i],
}, writer, level - 1, mod);
}
if (len > max_aggregate_items) {
@ -372,11 +389,28 @@ pub fn print(
return writer.writeAll(".{ ... }");
}
const payload = val.castTag(.slice).?.data;
try writer.writeAll(".{ ");
const elem_ty = ty.elemType2();
const len = payload.len.toUnsignedInt(target);
const max_len = std.math.min(len, max_aggregate_items);
if (elem_ty.eql(Type.u8, mod)) str: {
const max_len = @intCast(usize, std.math.min(len, max_string_len));
var buf: [max_string_len]u8 = undefined;
var i: u32 = 0;
while (i < max_len) : (i += 1) {
var elem_buf: Value.ElemValueBuffer = undefined;
const elem_val = payload.ptr.elemValueBuffer(mod, i, &elem_buf);
buf[i] = std.math.cast(u8, elem_val.toUnsignedInt(target)) orelse break :str;
}
// TODO would be nice if this had a bit of unicode awareness.
const truncated = if (len > max_string_len) " (truncated)" else "";
return writer.print("\"{}{s}\"", .{ std.zig.fmtEscapes(buf[0..max_len]), truncated });
}
try writer.writeAll(".{ ");
const max_len = std.math.min(len, max_aggregate_items);
var i: u32 = 0;
while (i < max_len) : (i += 1) {
if (i != 0) try writer.writeAll(", ");

View File

@ -95,3 +95,10 @@ test "@min for vectors" {
try S.doTheTest();
comptime try S.doTheTest();
}
test "@min/@max on lazy values" {
const A = extern struct { u8_4: [4]u8 };
const B = extern struct { u8_16: [16]u8 };
const size = @max(@sizeOf(A), @sizeOf(B));
try expect(size == @sizeOf(B));
}

View File

@ -1,17 +0,0 @@
extern fn foo(ptr: fn(*void) callconv(.C) void) void;
export fn entry() void {
foo(bar);
}
fn bar(x: *void) callconv(.C) void { _ = x; }
export fn entry2() void {
bar(&{});
}
// error
// backend=stage1
// target=native
//
// tmp.zig:1:23: error: parameter of type '*void' has 0 bits; not allowed in function with calling convention 'C'
// tmp.zig:7:11: error: parameter of type '*void' has 0 bits; not allowed in function with calling convention 'C'

View File

@ -1,12 +0,0 @@
fn foo() void {
const node: struct {} = undefined;
const vla_ptr = @ptrCast([*]const u8, &node);
_ = vla_ptr;
}
comptime { foo(); }
// error
// backend=stage1
// target=native
//
// tmp.zig:3:21: error: '*const struct:2:17' and '[*]const u8' do not have the same in-memory representation

View File

@ -1,16 +0,0 @@
const Set1 = error{A, C};
const Set2 = error{B, D};
export fn entry() void {
foo(Set1.A);
}
fn foo(x: Set1) void {
if (x == Set2.B) {
}
}
// error
// backend=stage1
// target=native
//
// tmp.zig:7:11: error: error sets 'Set1' and 'Set2' have no common errors

View File

@ -1,11 +0,0 @@
comptime {
var c_ptr: [*c]u8 = undefined;
var zig_ptr: *u8 = c_ptr;
_ = zig_ptr;
}
// error
// backend=stage1
// target=native
//
// tmp.zig:3:24: error: use of undefined value here causes undefined behavior

View File

@ -1,27 +0,0 @@
export fn foo1() void {
const a: *[1]u8 = undefined;
var b: []u8 = a;
_ = b;
}
export fn foo2() void {
comptime {
var a: *[1]u8 = undefined;
var b: []u8 = a;
_ = b;
}
}
export fn foo3() void {
comptime {
const a: *[1]u8 = undefined;
var b: []u8 = a;
_ = b;
}
}
// error
// backend=stage1
// target=native
//
// tmp.zig:3:19: error: use of undefined value here causes undefined behavior
// tmp.zig:9:23: error: use of undefined value here causes undefined behavior
// tmp.zig:16:23: error: use of undefined value here causes undefined behavior

View File

@ -1,9 +0,0 @@
export fn entry() bool {
return @ptrToInt(&{}) == @ptrToInt(&{});
}
// error
// backend=stage1
// target=native
//
// tmp.zig:2:23: error: pointer to size 0 type has no address

View File

@ -1,11 +0,0 @@
export fn entry() void {
var pointer: ?*u0 = null;
var x = @ptrToInt(pointer);
_ = x;
}
// error
// backend=stage1
// target=native
//
// tmp.zig:3:23: error: pointer to size 0 type has no address

View File

@ -1,18 +0,0 @@
export fn entry() void {
_ = @Type(.{ .Pointer = .{
.size = .One,
.is_const = false,
.is_volatile = false,
.alignment = 1,
.address_space = .gs,
.child = u8,
.is_allowzero = false,
.sentinel = null,
}});
}
// error
// backend=stage1
// target=native
//
// tmp.zig:2:16: error: address space 'gs' not available in stage 1 compiler, must be .generic

View File

@ -1,11 +0,0 @@
const builtin = @import("std").builtin;
var globalTypeInfo : builtin.Type = undefined;
export fn entry() void {
_ = @Type(globalTypeInfo);
}
// error
// backend=stage1
// target=native
//
// tmp.zig:4:15: error: unable to evaluate constant expression

View File

@ -1,10 +0,0 @@
var buf: *[1]u8 = undefined;
export fn entry() void {
_ = buf[0..1];
}
// error
// backend=stage1
// target=native
//
// tmp.zig:3:12: error: non-zero length slice of undefined pointer

View File

@ -1,17 +0,0 @@
export fn entry() void {
Test(i32);
}
fn Test(comptime T: type) void {
const x = switch (T) {
[]u8 => |x| x,
i32 => |x| x,
else => unreachable,
};
_ = x;
}
// error
// backend=stage1
// target=native
//
// tmp.zig:7:17: error: switch on type 'type' provides no expression parameter

View File

@ -1,13 +0,0 @@
const Cmd = struct {
exec: fn () void,
};
export fn entry() void {
const command = Cmd{ .exec = undefined };
command.exec();
}
// error
// backend=stage1
// target=native
//
// tmp.zig:6:12: error: use of undefined value here causes undefined behavior