aboutsummaryrefslogtreecommitdiff
path: root/src/codegen
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2023-10-21 21:38:55 -0400
committerGitHub <noreply@github.com>2023-10-21 21:38:55 -0400
commit7d50634e0ad4355e339bc243a2e2842693e133f9 (patch)
treecd6f81b82b20532d40e0944e6a814519ebf7cb41 /src/codegen
parent3cd3052d4d303dbae7d517fa40f6d171c957afdd (diff)
parent3d7c6c803b788138aa08f51cf4ee8cf7892e315d (diff)
downloadzig-7d50634e0ad4355e339bc243a2e2842693e133f9.tar.gz
zig-7d50634e0ad4355e339bc243a2e2842693e133f9.zip
Merge pull request #17545 from ziglang/more-anon-decls
migrate make_ptr_const to new anonymous decl mechanism
Diffstat (limited to 'src/codegen')
-rw-r--r--src/codegen/c.zig21
-rw-r--r--src/codegen/llvm.zig31
-rw-r--r--src/codegen/llvm/Builder.zig6
-rw-r--r--src/codegen/llvm/bindings.zig3
-rw-r--r--src/codegen/spirv.zig7
5 files changed, 52 insertions, 16 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig
index 94598985c0..897d0ea047 100644
--- a/src/codegen/c.zig
+++ b/src/codegen/c.zig
@@ -531,6 +531,7 @@ pub const DeclGen = struct {
/// Keeps track of anonymous decls that need to be rendered before this
/// (named) Decl in the output C code.
anon_decl_deps: std.AutoArrayHashMapUnmanaged(InternPool.Index, C.DeclBlock),
+ aligned_anon_decls: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment),
fn fail(dg: *DeclGen, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } {
@setCold(true);
@@ -548,11 +549,12 @@ pub const DeclGen = struct {
writer: anytype,
ty: Type,
ptr_val: Value,
- decl_val: InternPool.Index,
+ anon_decl: InternPool.Key.Ptr.Addr.AnonDecl,
location: ValueRenderLocation,
) error{ OutOfMemory, AnalysisFail }!void {
const mod = dg.module;
const ip = &mod.intern_pool;
+ const decl_val = anon_decl.val;
const decl_ty = ip.typeOf(decl_val).toType();
// Render an undefined pointer if we have a pointer to a zero-bit or comptime type.
@@ -592,8 +594,23 @@ pub const DeclGen = struct {
// Indicate that the anon decl should be rendered to the output so that
// our reference above is not undefined.
+ const ptr_type = ip.indexToKey(anon_decl.orig_ty).ptr_type;
const gop = try dg.anon_decl_deps.getOrPut(dg.gpa, decl_val);
if (!gop.found_existing) gop.value_ptr.* = .{};
+
+ // Only insert an alignment entry if the alignment is greater than ABI
+ // alignment. If there is already an entry, keep the greater alignment.
+ const explicit_alignment = ptr_type.flags.alignment;
+ if (explicit_alignment != .none) {
+ const abi_alignment = ptr_type.child.toType().abiAlignment(mod);
+ if (explicit_alignment.compareStrict(.gt, abi_alignment)) {
+ const aligned_gop = try dg.aligned_anon_decls.getOrPut(dg.gpa, decl_val);
+ aligned_gop.value_ptr.* = if (aligned_gop.found_existing)
+ aligned_gop.value_ptr.maxStrict(explicit_alignment)
+ else
+ explicit_alignment;
+ }
+ }
}
fn renderDeclValue(
@@ -651,7 +668,7 @@ pub const DeclGen = struct {
switch (ptr.addr) {
.decl => |d| try dg.renderDeclValue(writer, ptr_ty, ptr_val.toValue(), d, location),
.mut_decl => |md| try dg.renderDeclValue(writer, ptr_ty, ptr_val.toValue(), md.decl, location),
- .anon_decl => |decl_val| try dg.renderAnonDeclValue(writer, ptr_ty, ptr_val.toValue(), decl_val, location),
+ .anon_decl => |anon_decl| try dg.renderAnonDeclValue(writer, ptr_ty, ptr_val.toValue(), anon_decl, location),
.int => |int| {
try writer.writeByte('(');
try dg.renderCType(writer, ptr_cty);
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index cddd4340d7..ed4f1bdf6c 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -3049,10 +3049,19 @@ pub const Object = struct {
o: *Object,
decl_val: InternPool.Index,
llvm_addr_space: Builder.AddrSpace,
+ alignment: InternPool.Alignment,
) Error!Builder.Variable.Index {
+ assert(alignment != .none);
// TODO: Add address space to the anon_decl_map
const gop = try o.anon_decl_map.getOrPut(o.gpa, decl_val);
- if (gop.found_existing) return gop.value_ptr.ptr(&o.builder).kind.variable;
+ if (gop.found_existing) {
+ // Keep the greater of the two alignments.
+ const variable_index = gop.value_ptr.ptr(&o.builder).kind.variable;
+ const old_alignment = InternPool.Alignment.fromLlvm(variable_index.getAlignment(&o.builder));
+ const max_alignment = old_alignment.maxStrict(alignment);
+ variable_index.setAlignment(max_alignment.toLlvm(), &o.builder);
+ return variable_index;
+ }
errdefer assert(o.anon_decl_map.remove(decl_val));
const mod = o.module;
@@ -3068,6 +3077,7 @@ pub const Object = struct {
try variable_index.setInitializer(try o.lowerValue(decl_val), &o.builder);
variable_index.setLinkage(.internal, &o.builder);
variable_index.setUnnamedAddr(.unnamed_addr, &o.builder);
+ variable_index.setAlignment(alignment.toLlvm(), &o.builder);
return variable_index;
}
@@ -4250,13 +4260,6 @@ pub const Object = struct {
return o.builder.bigIntConst(try o.builder.intType(ty.intInfo(mod).bits), bigint);
}
- fn lowerParentPtrAnonDecl(o: *Object, decl_val: InternPool.Index) Error!Builder.Constant {
- const mod = o.module;
- const decl_ty = mod.intern_pool.typeOf(decl_val).toType();
- const ptr_ty = try mod.singleMutPtrType(decl_ty);
- return o.lowerAnonDeclRef(ptr_ty, decl_val);
- }
-
fn lowerParentPtrDecl(o: *Object, decl_index: Module.Decl.Index) Allocator.Error!Builder.Constant {
const mod = o.module;
const decl = mod.declPtr(decl_index);
@@ -4272,7 +4275,7 @@ pub const Object = struct {
return switch (ptr.addr) {
.decl => |decl| try o.lowerParentPtrDecl(decl),
.mut_decl => |mut_decl| try o.lowerParentPtrDecl(mut_decl.decl),
- .anon_decl => |anon_decl| try o.lowerParentPtrAnonDecl(anon_decl),
+ .anon_decl => |ad| try o.lowerAnonDeclRef(ad.orig_ty.toType(), ad),
.int => |int| try o.lowerIntAsPtr(int),
.eu_payload => |eu_ptr| {
const parent_ptr = try o.lowerParentPtr(eu_ptr.toValue());
@@ -4391,10 +4394,11 @@ pub const Object = struct {
fn lowerAnonDeclRef(
o: *Object,
ptr_ty: Type,
- decl_val: InternPool.Index,
+ anon_decl: InternPool.Key.Ptr.Addr.AnonDecl,
) Error!Builder.Constant {
const mod = o.module;
const ip = &mod.intern_pool;
+ const decl_val = anon_decl.val;
const decl_ty = ip.typeOf(decl_val).toType();
const target = mod.getTarget();
@@ -4413,9 +4417,10 @@ pub const Object = struct {
if (is_fn_body)
@panic("TODO");
- const addr_space = target_util.defaultAddressSpace(target, .global_constant);
- const llvm_addr_space = toLlvmAddressSpace(addr_space, target);
- const llvm_global = (try o.resolveGlobalAnonDecl(decl_val, llvm_addr_space)).ptrConst(&o.builder).global;
+ const orig_ty = anon_decl.orig_ty.toType();
+ const llvm_addr_space = toLlvmAddressSpace(orig_ty.ptrAddressSpace(mod), target);
+ const alignment = orig_ty.ptrAlignment(mod);
+ const llvm_global = (try o.resolveGlobalAnonDecl(decl_val, llvm_addr_space, alignment)).ptrConst(&o.builder).global;
const llvm_val = try o.builder.convConst(
.unneeded,
diff --git a/src/codegen/llvm/Builder.zig b/src/codegen/llvm/Builder.zig
index 5a9703af3d..4f971db1de 100644
--- a/src/codegen/llvm/Builder.zig
+++ b/src/codegen/llvm/Builder.zig
@@ -2477,6 +2477,12 @@ pub const Variable = struct {
self.ptr(builder).alignment = alignment;
}
+ pub fn getAlignment(self: Index, builder: *Builder) Alignment {
+ if (builder.useLibLlvm())
+ return Alignment.fromByteUnits(self.toLlvm(builder).getAlignment());
+ return self.ptr(builder).alignment;
+ }
+
pub fn toLlvm(self: Index, builder: *const Builder) *llvm.Value {
return self.ptrConst(builder).global.toLlvm(builder);
}
diff --git a/src/codegen/llvm/bindings.zig b/src/codegen/llvm/bindings.zig
index bb68e28bf2..d7144b36ce 100644
--- a/src/codegen/llvm/bindings.zig
+++ b/src/codegen/llvm/bindings.zig
@@ -273,6 +273,9 @@ pub const Value = opaque {
pub const setAlignment = LLVMSetAlignment;
extern fn LLVMSetAlignment(V: *Value, Bytes: c_uint) void;
+ pub const getAlignment = LLVMGetAlignment;
+ extern fn LLVMGetAlignment(V: *Value) c_uint;
+
pub const setFunctionCallConv = LLVMSetFunctionCallConv;
extern fn LLVMSetFunctionCallConv(Fn: *Value, CC: CallConv) void;
diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig
index ded73d6afd..e7e6ebdef3 100644
--- a/src/codegen/spirv.zig
+++ b/src/codegen/spirv.zig
@@ -959,12 +959,17 @@ const DeclGen = struct {
}
}
- fn constantAnonDeclRef(self: *DeclGen, ty: Type, decl_val: InternPool.Index) !IdRef {
+ fn constantAnonDeclRef(
+ self: *DeclGen,
+ ty: Type,
+ anon_decl: InternPool.Key.Ptr.Addr.AnonDecl,
+ ) !IdRef {
// TODO: Merge this function with constantDeclRef.
const mod = self.module;
const ip = &mod.intern_pool;
const ty_ref = try self.resolveType(ty, .direct);
+ const decl_val = anon_decl.val;
const decl_ty = ip.typeOf(decl_val).toType();
if (decl_val.toValue().getFunction(mod)) |func| {