aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/std/mem/Allocator.zig2
-rw-r--r--src/Compilation.zig2
-rw-r--r--src/Module.zig16
-rw-r--r--src/Sema.zig25
-rw-r--r--src/codegen/llvm.zig33
-rw-r--r--src/codegen/llvm/bindings.zig13
-rw-r--r--src/stage1/analyze.cpp6
-rw-r--r--src/zig_llvm.cpp12
-rw-r--r--src/zig_llvm.h6
-rw-r--r--test/behavior/call.zig17
-rw-r--r--test/behavior/eval.zig15
-rw-r--r--test/behavior/union.zig22
12 files changed, 146 insertions, 23 deletions
diff --git a/lib/std/mem/Allocator.zig b/lib/std/mem/Allocator.zig
index 28ca194c29..92347c0919 100644
--- a/lib/std/mem/Allocator.zig
+++ b/lib/std/mem/Allocator.zig
@@ -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];
}
diff --git a/src/Compilation.zig b/src/Compilation.zig
index 35be4e86cf..73db9f5e97 100644
--- a/src/Compilation.zig
+++ b/src/Compilation.zig
@@ -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
diff --git a/src/Module.zig b/src/Module.zig
index 3f061491c1..af29a591cc 100644
--- a/src/Module.zig
+++ b/src/Module.zig
@@ -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();
diff --git a/src/Sema.zig b/src/Sema.zig
index 493202982e..64b4bf97db 100644
--- a/src/Sema.zig
+++ b/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(
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index abe4256a30..af9dcacf48 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -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);
diff --git a/src/codegen/llvm/bindings.zig b/src/codegen/llvm/bindings.zig
index a5b01d6ddf..1b462312cd 100644
--- a/src/codegen/llvm/bindings.zig
+++ b/src/codegen/llvm/bindings.zig
@@ -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;
diff --git a/src/stage1/analyze.cpp b/src/stage1/analyze.cpp
index 59ca43644a..94ed3a2162 100644
--- a/src/stage1/analyze.cpp
+++ b/src/stage1/analyze.cpp
@@ -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
diff --git a/src/zig_llvm.cpp b/src/zig_llvm.cpp
index b5edb336a5..7134df6a9c 100644
--- a/src/zig_llvm.cpp
+++ b/src/zig_llvm.cpp
@@ -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);
}
diff --git a/src/zig_llvm.h b/src/zig_llvm.h
index 1a4d5481b6..0e210f9545 100644
--- a/src/zig_llvm.h
+++ b/src/zig_llvm.h
@@ -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,
diff --git a/test/behavior/call.zig b/test/behavior/call.zig
index a8d59bddff..0414e1d575 100644
--- a/test/behavior/call.zig
+++ b/test/behavior/call.zig
@@ -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 }});
+}
diff --git a/test/behavior/eval.zig b/test/behavior/eval.zig
index cd0891990c..145be9dede 100644
--- a/test/behavior/eval.zig
+++ b/test/behavior/eval.zig
@@ -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);
+}
diff --git a/test/behavior/union.zig b/test/behavior/union.zig
index d473debe1f..37cd72e319 100644
--- a/test/behavior/union.zig
+++ b/test/behavior/union.zig
@@ -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());
+}