mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
Merge pull request #13558 from Vexu/stage2-fixes
Stage2 bug fixes to get third party projects building
This commit is contained in:
parent
9e50cb294b
commit
4ed0cd51c0
@ -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];
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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();
|
||||
|
||||
25
src/Sema.zig
25
src/Sema.zig
@ -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(
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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 }});
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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());
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user