codegen: implement lowering aligned anon decls

This commit is contained in:
Jacob Young 2023-10-19 21:23:09 -04:00 committed by Andrew Kelley
parent dd402f6d83
commit c4fcf0e22a
7 changed files with 73 additions and 57 deletions

View File

@ -3153,11 +3153,8 @@ fn lowerAnonDeclRef(
return WValue{ .imm32 = 0xaaaaaaaa };
}
const alignment = mod.intern_pool.indexToKey(anon_decl.orig_ty).ptr_type.flags.alignment;
if (alignment != .none) {
@panic("TODO how to make this anon decl be aligned?");
}
const res = try func.bin_file.lowerAnonDecl(decl_val, func.decl.srcLoc(mod));
const decl_align = mod.intern_pool.indexToKey(anon_decl.orig_ty).ptr_type.flags.alignment;
const res = try func.bin_file.lowerAnonDecl(decl_val, decl_align, func.decl.srcLoc(mod));
switch (res) {
.ok => {},
.fail => |em| {

View File

@ -731,16 +731,13 @@ fn lowerAnonDeclRef(
return Result.ok;
}
const res = try bin_file.lowerAnonDecl(decl_val, src_loc);
const decl_align = mod.intern_pool.indexToKey(anon_decl.orig_ty).ptr_type.flags.alignment;
const res = try bin_file.lowerAnonDecl(decl_val, decl_align, src_loc);
switch (res) {
.ok => {},
.fail => |em| return .{ .fail = em },
}
const alignment = mod.intern_pool.indexToKey(anon_decl.orig_ty).ptr_type.flags.alignment;
if (alignment != .none) {
@panic("TODO how to make this anon decl be aligned?");
}
const vaddr = try bin_file.getAnonDeclVAddr(decl_val, .{
.parent_atom_index = reloc_info.parent_atom_index,
.offset = code.items.len,

View File

@ -940,15 +940,15 @@ pub const File = struct {
pub const LowerResult = @import("codegen.zig").Result;
pub fn lowerAnonDecl(base: *File, decl_val: InternPool.Index, src_loc: Module.SrcLoc) !LowerResult {
pub fn lowerAnonDecl(base: *File, decl_val: InternPool.Index, decl_align: InternPool.Alignment, src_loc: Module.SrcLoc) !LowerResult {
if (build_options.only_c) unreachable;
switch (base.tag) {
.coff => return @fieldParentPtr(Coff, "base", base).lowerAnonDecl(decl_val, src_loc),
.elf => return @fieldParentPtr(Elf, "base", base).lowerAnonDecl(decl_val, src_loc),
.macho => return @fieldParentPtr(MachO, "base", base).lowerAnonDecl(decl_val, src_loc),
.coff => return @fieldParentPtr(Coff, "base", base).lowerAnonDecl(decl_val, decl_align, src_loc),
.elf => return @fieldParentPtr(Elf, "base", base).lowerAnonDecl(decl_val, decl_align, src_loc),
.macho => return @fieldParentPtr(MachO, "base", base).lowerAnonDecl(decl_val, decl_align, src_loc),
.plan9 => return @fieldParentPtr(Plan9, "base", base).lowerAnonDecl(decl_val, src_loc),
.c => unreachable,
.wasm => return @fieldParentPtr(Wasm, "base", base).lowerAnonDecl(decl_val, src_loc),
.wasm => return @fieldParentPtr(Wasm, "base", base).lowerAnonDecl(decl_val, decl_align, src_loc),
.spirv => unreachable,
.nvptx => unreachable,
}

View File

@ -1091,7 +1091,7 @@ pub fn lowerUnnamedConst(self: *Coff, tv: TypedValue, decl_index: Module.Decl.In
const index = unnamed_consts.items.len;
const sym_name = try std.fmt.allocPrint(gpa, "__unnamed_{s}_{d}", .{ decl_name, index });
defer gpa.free(sym_name);
const atom_index = switch (try self.lowerConst(sym_name, tv, self.rdata_section_index.?, decl.srcLoc(mod))) {
const atom_index = switch (try self.lowerConst(sym_name, tv, tv.ty.abiAlignment(mod), self.rdata_section_index.?, decl.srcLoc(mod))) {
.ok => |atom_index| atom_index,
.fail => |em| {
decl.analysis = .codegen_failure;
@ -1109,13 +1109,12 @@ const LowerConstResult = union(enum) {
fail: *Module.ErrorMsg,
};
fn lowerConst(self: *Coff, name: []const u8, tv: TypedValue, sect_id: u16, src_loc: Module.SrcLoc) !LowerConstResult {
fn lowerConst(self: *Coff, name: []const u8, tv: TypedValue, required_alignment: InternPool.Alignment, sect_id: u16, src_loc: Module.SrcLoc) !LowerConstResult {
const gpa = self.base.allocator;
var code_buffer = std.ArrayList(u8).init(gpa);
defer code_buffer.deinit();
const mod = self.base.options.module.?;
const atom_index = try self.createAtom();
const sym = self.getAtom(atom_index).getSymbolPtr(self);
try self.setSymbolName(sym, name);
@ -1129,10 +1128,13 @@ fn lowerConst(self: *Coff, name: []const u8, tv: TypedValue, sect_id: u16, src_l
.fail => |em| return .{ .fail = em },
};
const required_alignment: u32 = @intCast(tv.ty.abiAlignment(mod).toByteUnits(0));
const atom = self.getAtomPtr(atom_index);
atom.size = @as(u32, @intCast(code.len));
atom.getSymbolPtr(self).value = try self.allocateAtom(atom_index, atom.size, required_alignment);
atom.getSymbolPtr(self).value = try self.allocateAtom(
atom_index,
atom.size,
@intCast(required_alignment.toByteUnitsOptional().?),
);
errdefer self.freeAtom(atom_index);
log.debug("allocated atom for {s} at 0x{x}", .{ name, atom.getSymbol(self).value });
@ -1736,7 +1738,7 @@ pub fn getDeclVAddr(self: *Coff, decl_index: Module.Decl.Index, reloc_info: link
return 0;
}
pub fn lowerAnonDecl(self: *Coff, decl_val: InternPool.Index, src_loc: Module.SrcLoc) !codegen.Result {
pub fn lowerAnonDecl(self: *Coff, decl_val: InternPool.Index, decl_align: InternPool.Alignment, src_loc: Module.SrcLoc) !codegen.Result {
// This is basically the same as lowerUnnamedConst.
// example:
// const ty = mod.intern_pool.typeOf(decl_val).toType();
@ -1747,15 +1749,21 @@ pub fn lowerAnonDecl(self: *Coff, decl_val: InternPool.Index, src_loc: Module.Sr
// to put it in some location.
// ...
const gpa = self.base.allocator;
const mod = self.base.options.module.?;
const ty = mod.intern_pool.typeOf(decl_val).toType();
const gop = try self.anon_decls.getOrPut(gpa, decl_val);
if (!gop.found_existing) {
const mod = self.base.options.module.?;
const ty = mod.intern_pool.typeOf(decl_val).toType();
const required_alignment = switch (decl_align) {
.none => ty.abiAlignment(mod),
else => decl_align,
};
if (!gop.found_existing or
!required_alignment.check(self.getAtom(gop.value_ptr.*).getSymbol(self).value))
{
const val = decl_val.toValue();
const tv = TypedValue{ .ty = ty, .val = val };
const name = try std.fmt.allocPrint(gpa, "__anon_{d}", .{@intFromEnum(decl_val)});
defer gpa.free(name);
const res = self.lowerConst(name, tv, self.rdata_section_index.?, src_loc) catch |err| switch (err) {
const res = self.lowerConst(name, tv, required_alignment, self.rdata_section_index.?, src_loc) catch |err| switch (err) {
else => {
// TODO improve error message
const em = try Module.ErrorMsg.create(gpa, src_loc, "lowerAnonDecl failed with error: {s}", .{

View File

@ -473,7 +473,7 @@ pub fn getDeclVAddr(self: *Elf, decl_index: Module.Decl.Index, reloc_info: link.
return vaddr;
}
pub fn lowerAnonDecl(self: *Elf, decl_val: InternPool.Index, src_loc: Module.SrcLoc) !codegen.Result {
pub fn lowerAnonDecl(self: *Elf, decl_val: InternPool.Index, decl_align: InternPool.Alignment, src_loc: Module.SrcLoc) !codegen.Result {
// This is basically the same as lowerUnnamedConst.
// example:
// const ty = mod.intern_pool.typeOf(decl_val).toType();
@ -484,15 +484,21 @@ pub fn lowerAnonDecl(self: *Elf, decl_val: InternPool.Index, src_loc: Module.Src
// to put it in some location.
// ...
const gpa = self.base.allocator;
const mod = self.base.options.module.?;
const ty = mod.intern_pool.typeOf(decl_val).toType();
const gop = try self.anon_decls.getOrPut(gpa, decl_val);
if (!gop.found_existing) {
const mod = self.base.options.module.?;
const ty = mod.intern_pool.typeOf(decl_val).toType();
const required_alignment = switch (decl_align) {
.none => ty.abiAlignment(mod),
else => decl_align,
};
if (!gop.found_existing or
required_alignment.order(self.symbol(gop.value_ptr.*).atom(self).?.alignment).compare(.gt))
{
const val = decl_val.toValue();
const tv = TypedValue{ .ty = ty, .val = val };
const name = try std.fmt.allocPrint(gpa, "__anon_{d}", .{@intFromEnum(decl_val)});
defer gpa.free(name);
const res = self.lowerConst(name, tv, self.zig_rodata_section_index.?, src_loc) catch |err| switch (err) {
const res = self.lowerConst(name, tv, required_alignment, self.zig_rodata_section_index.?, src_loc) catch |err| switch (err) {
else => {
// TODO improve error message
const em = try Module.ErrorMsg.create(gpa, src_loc, "lowerAnonDecl failed with error: {s}", .{
@ -3479,7 +3485,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module
const index = unnamed_consts.items.len;
const name = try std.fmt.allocPrint(gpa, "__unnamed_{s}_{d}", .{ decl_name, index });
defer gpa.free(name);
const sym_index = switch (try self.lowerConst(name, typed_value, self.zig_rodata_section_index.?, decl.srcLoc(mod))) {
const sym_index = switch (try self.lowerConst(name, typed_value, typed_value.ty.abiAlignment(mod), self.zig_rodata_section_index.?, decl.srcLoc(mod))) {
.ok => |sym_index| sym_index,
.fail => |em| {
decl.analysis = .codegen_failure;
@ -3502,6 +3508,7 @@ fn lowerConst(
self: *Elf,
name: []const u8,
tv: TypedValue,
required_alignment: InternPool.Alignment,
output_section_index: u16,
src_loc: Module.SrcLoc,
) !LowerConstResult {
@ -3510,7 +3517,6 @@ fn lowerConst(
var code_buffer = std.ArrayList(u8).init(gpa);
defer code_buffer.deinit();
const mod = self.base.options.module.?;
const zig_module = self.file(self.zig_module_index.?).?.zig_module;
const sym_index = try zig_module.addAtom(self);
@ -3524,7 +3530,6 @@ fn lowerConst(
.fail => |em| return .{ .fail = em },
};
const required_alignment = tv.ty.abiAlignment(mod);
const phdr_index = self.phdr_to_shdr_table.get(output_section_index).?;
const local_sym = self.symbol(sym_index);
const name_str_index = try self.strtab.insert(gpa, name);

View File

@ -2196,7 +2196,7 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: Modu
const index = unnamed_consts.items.len;
const name = try std.fmt.allocPrint(gpa, "___unnamed_{s}_{d}", .{ decl_name, index });
defer gpa.free(name);
const atom_index = switch (try self.lowerConst(name, typed_value, self.data_const_section_index.?, decl.srcLoc(mod))) {
const atom_index = switch (try self.lowerConst(name, typed_value, typed_value.ty.abiAlignment(mod), self.data_const_section_index.?, decl.srcLoc(mod))) {
.ok => |atom_index| atom_index,
.fail => |em| {
decl.analysis = .codegen_failure;
@ -2219,6 +2219,7 @@ fn lowerConst(
self: *MachO,
name: []const u8,
tv: TypedValue,
required_alignment: InternPool.Alignment,
sect_id: u8,
src_loc: Module.SrcLoc,
) !LowerConstResult {
@ -2227,8 +2228,6 @@ fn lowerConst(
var code_buffer = std.ArrayList(u8).init(gpa);
defer code_buffer.deinit();
const mod = self.base.options.module.?;
log.debug("allocating symbol indexes for {s}", .{name});
const sym_index = try self.allocateSymbol();
@ -2243,7 +2242,6 @@ fn lowerConst(
.fail => |em| return .{ .fail = em },
};
const required_alignment = tv.ty.abiAlignment(mod);
const atom = self.getAtomPtr(atom_index);
atom.size = code.len;
// TODO: work out logic for disambiguating functions from function pointers
@ -2868,7 +2866,7 @@ pub fn getDeclVAddr(self: *MachO, decl_index: Module.Decl.Index, reloc_info: Fil
return 0;
}
pub fn lowerAnonDecl(self: *MachO, decl_val: InternPool.Index, src_loc: Module.SrcLoc) !codegen.Result {
pub fn lowerAnonDecl(self: *MachO, decl_val: InternPool.Index, decl_align: InternPool.Alignment, src_loc: Module.SrcLoc) !codegen.Result {
// This is basically the same as lowerUnnamedConst.
// example:
// const ty = mod.intern_pool.typeOf(decl_val).toType();
@ -2879,15 +2877,21 @@ pub fn lowerAnonDecl(self: *MachO, decl_val: InternPool.Index, src_loc: Module.S
// to put it in some location.
// ...
const gpa = self.base.allocator;
const mod = self.base.options.module.?;
const ty = mod.intern_pool.typeOf(decl_val).toType();
const gop = try self.anon_decls.getOrPut(gpa, decl_val);
if (!gop.found_existing) {
const mod = self.base.options.module.?;
const ty = mod.intern_pool.typeOf(decl_val).toType();
const required_alignment = switch (decl_align) {
.none => ty.abiAlignment(mod),
else => decl_align,
};
if (!gop.found_existing or
!required_alignment.check(self.getAtom(gop.value_ptr.*).getSymbol(self).n_value))
{
const val = decl_val.toValue();
const tv = TypedValue{ .ty = ty, .val = val };
const name = try std.fmt.allocPrint(gpa, "__anon_{d}", .{@intFromEnum(decl_val)});
defer gpa.free(name);
const res = self.lowerConst(name, tv, self.data_const_section_index.?, src_loc) catch |err| switch (err) {
const res = self.lowerConst(name, tv, required_alignment, self.data_const_section_index.?, src_loc) catch |err| switch (err) {
else => {
// TODO improve error message
const em = try Module.ErrorMsg.create(gpa, src_loc, "lowerAnonDecl failed with error: {s}", .{

View File

@ -1702,25 +1702,30 @@ pub fn getDeclVAddr(
return target_symbol_index;
}
pub fn lowerAnonDecl(wasm: *Wasm, decl_val: InternPool.Index, src_loc: Module.SrcLoc) !codegen.Result {
pub fn lowerAnonDecl(wasm: *Wasm, decl_val: InternPool.Index, decl_align: Alignment, src_loc: Module.SrcLoc) !codegen.Result {
const gop = try wasm.anon_decls.getOrPut(wasm.base.allocator, decl_val);
if (gop.found_existing) {
return .ok;
if (!gop.found_existing) {
const mod = wasm.base.options.module.?;
const ty = mod.intern_pool.typeOf(decl_val).toType();
const tv: TypedValue = .{ .ty = ty, .val = decl_val.toValue() };
const name = try std.fmt.allocPrintZ(wasm.base.allocator, "__anon_{d}", .{@intFromEnum(decl_val)});
defer wasm.base.allocator.free(name);
switch (try wasm.lowerConst(name, tv, src_loc)) {
.ok => |atom_index| gop.value_ptr.* = atom_index,
.fail => |em| return .{ .fail = em },
}
}
const mod = wasm.base.options.module.?;
const ty = mod.intern_pool.typeOf(decl_val).toType();
const tv: TypedValue = .{ .ty = ty, .val = decl_val.toValue() };
const name = try std.fmt.allocPrintZ(wasm.base.allocator, "__anon_{d}", .{@intFromEnum(decl_val)});
defer wasm.base.allocator.free(name);
switch (try wasm.lowerConst(name, tv, src_loc)) {
.ok => |atom_index| {
gop.value_ptr.* = atom_index;
return .ok;
const atom = wasm.getAtomPtr(gop.value_ptr.*);
atom.alignment = switch (atom.alignment) {
.none => decl_align,
else => switch (decl_align) {
.none => atom.alignment,
else => atom.alignment.maxStrict(decl_align),
},
.fail => |em| return .{ .fail = em },
}
};
return .ok;
}
pub fn getAnonDeclVAddr(wasm: *Wasm, decl_val: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 {