Merge pull request #13558 from Vexu/stage2-fixes

Stage2 bug fixes to get third party projects building
This commit is contained in:
Veikka Tuominen 2022-11-16 12:56:51 +02:00 committed by Andrew Kelley
parent 9e50cb294b
commit 4ed0cd51c0
12 changed files with 146 additions and 23 deletions

View File

@ -167,7 +167,7 @@ pub inline fn rawFree(self: Allocator, buf: []u8, buf_align: u29, ret_addr: usiz
/// Returns a pointer to undefined memory.
/// Call `destroy` with the result to free the memory.
pub fn create(self: Allocator, comptime T: type) Error!*T {
if (@sizeOf(T) == 0) return @as(*T, undefined);
if (@sizeOf(T) == 0) return @intToPtr(*T, std.math.maxInt(usize));
const slice = try self.allocAdvancedWithRetAddr(T, null, 1, .exact, @returnAddress());
return &slice[0];
}

View File

@ -2361,7 +2361,7 @@ pub fn update(comp: *Compilation) !void {
// The `test_functions` decl has been intentionally postponed until now,
// at which point we must populate it with the list of test functions that
// have been discovered and not filtered out.
try module.populateTestFunctions();
try module.populateTestFunctions(main_progress_node);
}
// Process the deletion set. We use a while loop here because the

View File

@ -6431,13 +6431,27 @@ pub fn processExports(mod: *Module) !void {
}
}
pub fn populateTestFunctions(mod: *Module) !void {
pub fn populateTestFunctions(
mod: *Module,
main_progress_node: *std.Progress.Node,
) !void {
const gpa = mod.gpa;
const builtin_pkg = mod.main_pkg.table.get("builtin").?;
const builtin_file = (mod.importPkg(builtin_pkg) catch unreachable).file;
const root_decl = mod.declPtr(builtin_file.root_decl.unwrap().?);
const builtin_namespace = root_decl.src_namespace;
const decl_index = builtin_namespace.decls.getKeyAdapted(@as([]const u8, "test_functions"), DeclAdapter{ .mod = mod }).?;
{
// We have to call `ensureDeclAnalyzed` here in case `builtin.test_functions`
// was not referenced by start code.
mod.sema_prog_node = main_progress_node.start("Semantic Analysis", 0);
mod.sema_prog_node.activate();
defer {
mod.sema_prog_node.end();
mod.sema_prog_node = undefined;
}
try mod.ensureDeclAnalyzed(decl_index);
}
const decl = mod.declPtr(decl_index);
var buf: Type.SlicePtrFieldTypeBuffer = undefined;
const tmp_test_fn_ty = decl.ty.slicePtrFieldType(&buf).elemType();

View File

@ -6361,6 +6361,7 @@ fn analyzeCall(
is_comptime_call,
&should_memoize,
memoized_call_key,
func_ty_info.param_types,
) catch |err| switch (err) {
error.NeededSourceLocation => {
_ = sema.inst_map.remove(inst);
@ -6376,6 +6377,7 @@ fn analyzeCall(
is_comptime_call,
&should_memoize,
memoized_call_key,
func_ty_info.param_types,
);
return error.AnalysisFail;
},
@ -6612,6 +6614,7 @@ fn analyzeInlineCallArg(
is_comptime_call: bool,
should_memoize: *bool,
memoized_call_key: Module.MemoizedCall.Key,
raw_param_types: []const Type,
) !void {
const zir_tags = sema.code.instructions.items(.tag);
switch (zir_tags[inst]) {
@ -6622,8 +6625,12 @@ fn analyzeInlineCallArg(
const param_src = pl_tok.src();
const extra = sema.code.extraData(Zir.Inst.Param, pl_tok.payload_index);
const param_body = sema.code.extra[extra.end..][0..extra.data.body_len];
const param_ty_inst = try sema.resolveBody(param_block, param_body, inst);
const param_ty = try sema.analyzeAsType(param_block, param_src, param_ty_inst);
const param_ty = param_ty: {
const raw_param_ty = raw_param_types[arg_i.*];
if (raw_param_ty.tag() != .generic_poison) break :param_ty raw_param_ty;
const param_ty_inst = try sema.resolveBody(param_block, param_body, inst);
break :param_ty try sema.analyzeAsType(param_block, param_src, param_ty_inst);
};
new_fn_info.param_types[arg_i.*] = param_ty;
const uncasted_arg = uncasted_args[arg_i.*];
if (try sema.typeRequiresComptime(param_ty)) {
@ -18754,7 +18761,7 @@ fn zirIntToPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
const addr = val.toUnsignedInt(target);
if (!ptr_ty.isAllowzeroPtr() and addr == 0)
return sema.fail(block, operand_src, "pointer type '{}' does not allow address zero", .{ptr_ty.fmt(sema.mod)});
if (addr != 0 and addr % ptr_align != 0)
if (addr != 0 and ptr_align != 0 and addr % ptr_align != 0)
return sema.fail(block, operand_src, "pointer type '{}' requires aligned address", .{ptr_ty.fmt(sema.mod)});
const val_payload = try sema.arena.create(Value.Payload.U64);
@ -22469,13 +22476,12 @@ fn fieldVal(
);
},
.Union => {
const union_ty = try sema.resolveTypeFields(child_type);
if (union_ty.getNamespace()) |namespace| {
if (child_type.getNamespace()) |namespace| {
if (try sema.namespaceLookupVal(block, src, namespace, field_name)) |inst| {
return inst;
}
}
const union_ty = try sema.resolveTypeFields(child_type);
if (union_ty.unionTagType()) |enum_ty| {
if (enum_ty.enumFieldIndex(field_name)) |field_index_usize| {
const field_index = @intCast(u32, field_index_usize);
@ -27397,6 +27403,13 @@ fn analyzeRef(
const operand_ty = sema.typeOf(operand);
if (try sema.resolveMaybeUndefVal(operand)) |val| {
switch (val.tag()) {
.extern_fn, .function => {
const decl_index = val.pointerDecl().?;
return sema.analyzeDeclRef(decl_index);
},
else => {},
}
var anon_decl = try block.startAnonDecl();
defer anon_decl.deinit();
return sema.analyzeDeclRef(try anon_decl.finish(

View File

@ -1507,6 +1507,11 @@ pub const Object = struct {
};
const field_index_val = Value.initPayload(&buf_field_index.base);
var buffer: Type.Payload.Bits = undefined;
const int_ty = ty.intTagType(&buffer);
const int_info = ty.intInfo(target);
assert(int_info.bits != 0);
for (field_names) |field_name, i| {
const field_name_z = try gpa.dupeZ(u8, field_name);
defer gpa.free(field_name_z);
@ -1514,9 +1519,25 @@ pub const Object = struct {
buf_field_index.data = @intCast(u32, i);
var buf_u64: Value.Payload.U64 = undefined;
const field_int_val = field_index_val.enumToInt(ty, &buf_u64);
// See https://github.com/ziglang/zig/issues/645
const field_int = field_int_val.toSignedInt();
enumerators[i] = dib.createEnumerator(field_name_z, field_int);
var bigint_space: Value.BigIntSpace = undefined;
const bigint = field_int_val.toBigInt(&bigint_space, target);
if (bigint.limbs.len == 1) {
enumerators[i] = dib.createEnumerator(field_name_z, bigint.limbs[0], int_info.signedness == .unsigned);
continue;
}
if (@sizeOf(usize) == @sizeOf(u64)) {
enumerators[i] = dib.createEnumerator2(
field_name_z,
@intCast(c_uint, bigint.limbs.len),
bigint.limbs.ptr,
int_info.bits,
int_info.signedness == .unsigned,
);
continue;
}
@panic("TODO implement bigint debug enumerators to llvm int for 32-bit compiler builds");
}
const di_file = try o.getDIFile(gpa, owner_decl.src_namespace.file_scope);
@ -1524,8 +1545,6 @@ pub const Object = struct {
const name = try ty.nameAlloc(gpa, o.module);
defer gpa.free(name);
var buffer: Type.Payload.Bits = undefined;
const int_ty = ty.intTagType(&buffer);
const enum_di_ty = dib.createEnumerationType(
di_scope,
@ -2118,7 +2137,8 @@ pub const Object = struct {
break :blk fwd_decl;
};
if (!ty.hasRuntimeBitsIgnoreComptime()) {
const union_obj = ty.cast(Type.Payload.Union).?.data;
if (!union_obj.haveFieldTypes() or !ty.hasRuntimeBitsIgnoreComptime()) {
const union_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index);
dib.replaceTemporary(fwd_decl, union_di_ty);
// The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`
@ -2128,7 +2148,6 @@ pub const Object = struct {
}
const layout = ty.unionGetLayout(target);
const union_obj = ty.cast(Type.Payload.Union).?.data;
if (layout.payload_size == 0) {
const tag_di_ty = try o.lowerDebugType(union_obj.tag_ty, .full);

View File

@ -1662,7 +1662,18 @@ pub const DIBuilder = opaque {
extern fn ZigLLVMCreateDebugEnumerator(
dib: *DIBuilder,
name: [*:0]const u8,
val: i64,
val: u64,
is_unsigned: bool,
) *DIEnumerator;
pub const createEnumerator2 = ZigLLVMCreateDebugEnumeratorOfArbitraryPrecision;
extern fn ZigLLVMCreateDebugEnumeratorOfArbitraryPrecision(
dib: *DIBuilder,
name: [*:0]const u8,
num_words: c_uint,
words: [*]const u64,
bits: c_uint,
is_unsigned: bool,
) *DIEnumerator;
pub const createEnumerationType = ZigLLVMCreateDebugEnumerationType;

View File

@ -9117,7 +9117,7 @@ static void resolve_llvm_types_enum(CodeGen *g, ZigType *enum_type, ResolveStatu
// https://github.com/ziglang/zig/issues/645
di_enumerators[i] = ZigLLVMCreateDebugEnumerator(g->dbuilder, buf_ptr(enum_field->name),
bigint_as_signed(&enum_field->value));
bigint_as_signed(&enum_field->value), false);
}
ZigType *tag_int_type = enum_type->data.enumeration.tag_int_type;
@ -9728,10 +9728,10 @@ static void resolve_llvm_types_anyerror(CodeGen *g) {
entry->llvm_type = get_llvm_type(g, g->err_tag_type);
ZigList<ZigLLVMDIEnumerator *> err_enumerators = {};
// reserve index 0 to indicate no error
err_enumerators.append(ZigLLVMCreateDebugEnumerator(g->dbuilder, "(none)", 0));
err_enumerators.append(ZigLLVMCreateDebugEnumerator(g->dbuilder, "(none)", 0, false));
for (size_t i = 1; i < g->errors_by_index.length; i += 1) {
ErrorTableEntry *error_entry = g->errors_by_index.at(i);
err_enumerators.append(ZigLLVMCreateDebugEnumerator(g->dbuilder, buf_ptr(&error_entry->name), i));
err_enumerators.append(ZigLLVMCreateDebugEnumerator(g->dbuilder, buf_ptr(&error_entry->name), i, false));
}
// create debug type for error sets

View File

@ -594,8 +594,16 @@ ZigLLVMDIType *ZigLLVMCreateDebugArrayType(ZigLLVMDIBuilder *dibuilder, uint64_t
return reinterpret_cast<ZigLLVMDIType*>(di_type);
}
ZigLLVMDIEnumerator *ZigLLVMCreateDebugEnumerator(ZigLLVMDIBuilder *dibuilder, const char *name, int64_t val) {
DIEnumerator *di_enumerator = reinterpret_cast<DIBuilder*>(dibuilder)->createEnumerator(name, val);
ZigLLVMDIEnumerator *ZigLLVMCreateDebugEnumerator(ZigLLVMDIBuilder *dibuilder, const char *name, uint64_t val, bool isUnsigned) {
DIEnumerator *di_enumerator = reinterpret_cast<DIBuilder*>(dibuilder)->createEnumerator(name, val, isUnsigned);
return reinterpret_cast<ZigLLVMDIEnumerator*>(di_enumerator);
}
ZigLLVMDIEnumerator *ZigLLVMCreateDebugEnumeratorOfArbitraryPrecision(ZigLLVMDIBuilder *dibuilder,
const char *name, unsigned NumWords, const uint64_t Words[], unsigned int bits, bool isUnsigned)
{
DIEnumerator *di_enumerator = reinterpret_cast<DIBuilder*>(dibuilder)->createEnumerator(name,
APSInt(APInt(bits, makeArrayRef(Words, NumWords)), isUnsigned));
return reinterpret_cast<ZigLLVMDIEnumerator*>(di_enumerator);
}

View File

@ -176,7 +176,11 @@ ZIG_EXTERN_C struct ZigLLVMDIType *ZigLLVMCreateDebugArrayType(struct ZigLLVMDIB
int elem_count);
ZIG_EXTERN_C struct ZigLLVMDIEnumerator *ZigLLVMCreateDebugEnumerator(struct ZigLLVMDIBuilder *dibuilder,
const char *name, int64_t val);
const char *name, uint64_t val, bool isUnsigned);
ZIG_EXTERN_C struct ZigLLVMDIEnumerator *ZigLLVMCreateDebugEnumeratorOfArbitraryPrecision(struct ZigLLVMDIBuilder *dibuilder,
const char *name, unsigned NumWords, const uint64_t Words[], unsigned int bits, bool isUnsigned);
ZIG_EXTERN_C struct ZigLLVMDIType *ZigLLVMCreateDebugEnumerationType(struct ZigLLVMDIBuilder *dibuilder,
struct ZigLLVMDIScope *scope, const char *name, struct ZigLLVMDIFile *file, unsigned line_number,

View File

@ -327,3 +327,20 @@ test "inline call preserves tail call" {
S.foo();
try expect(S.a == std.math.maxInt(u16));
}
test "inline call doesn't re-evaluate non generic struct" {
if (builtin.zig_backend == .stage1) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
const S = struct {
fn foo(f: struct { a: u8, b: u8 }) !void {
try expect(f.a == 123);
try expect(f.b == 45);
}
};
const ArgTuple = std.meta.ArgsTuple(@TypeOf(S.foo));
try @call(.{ .modifier = .always_inline }, S.foo, ArgTuple{.{ .a = 123, .b = 45 }});
comptime try @call(.{ .modifier = .always_inline }, S.foo, ArgTuple{.{ .a = 123, .b = 45 }});
}

View File

@ -1507,3 +1507,18 @@ test "inline call in @TypeOf inherits is_inline property" {
};
try expect(S.T == void);
}
test "comptime function turns function value to function pointer" {
const S = struct {
fn fnPtr(function: anytype) *const @TypeOf(function) {
return &function;
}
fn Nil() u8 {
return 0;
}
const foo = &[_]*const fn () u8{
fnPtr(Nil),
};
};
comptime try expect(S.foo[0] == &S.Nil);
}

View File

@ -1388,3 +1388,25 @@ test "packed union in packed struct" {
const a: S = .{ .nested = .{ .foo = 123 }, .bar = 5 };
try expect(a.unpack() == 123);
}
test "Namespace-like union" {
const DepType = enum {
git,
http,
const DepType = @This();
const Version = union(DepType) {
git: Git,
http: void,
const Git = enum {
branch,
tag,
commit,
fn frozen(self: Git) bool {
return self == .tag;
}
};
};
};
var a: DepType.Version.Git = .tag;
try expect(a.frozen());
}