aboutsummaryrefslogtreecommitdiff
path: root/src/codegen.zig
diff options
context:
space:
mode:
authorJacob Young <jacobly0@users.noreply.github.com>2024-04-08 12:44:42 -0400
committerJacob Young <jacobly0@users.noreply.github.com>2024-04-08 13:24:08 -0400
commit7611d90ba011fb030523e669e85acfb6faae5d19 (patch)
treef1b48f3ac73681c402dce10b5857ecc0f84dd7a4 /src/codegen.zig
parent4cd92567e7392b0fe390562d7ea52f68357bb45a (diff)
downloadzig-7611d90ba011fb030523e669e85acfb6faae5d19.tar.gz
zig-7611d90ba011fb030523e669e85acfb6faae5d19.zip
InternPool: remove slice from byte aggregate keys
This deletes a ton of lookups and avoids many UAF bugs. Closes #19485
Diffstat (limited to 'src/codegen.zig')
-rw-r--r--src/codegen.zig107
1 files changed, 50 insertions, 57 deletions
diff --git a/src/codegen.zig b/src/codegen.zig
index 76be8be974..b45777564a 100644
--- a/src/codegen.zig
+++ b/src/codegen.zig
@@ -97,7 +97,7 @@ fn writeFloat(comptime F: type, f: F, target: Target, endian: std.builtin.Endian
_ = target;
const bits = @typeInfo(F).Float.bits;
const Int = @Type(.{ .Int = .{ .signedness = .unsigned, .bits = bits } });
- const int = @as(Int, @bitCast(f));
+ const int: Int = @bitCast(f);
mem.writeInt(Int, code[0..@divExact(bits, 8)], int, endian);
}
@@ -136,24 +136,24 @@ pub fn generateLazySymbol(
if (lazy_sym.ty.isAnyError(zcu)) {
alignment.* = .@"4";
const err_names = zcu.global_error_set.keys();
- mem.writeInt(u32, try code.addManyAsArray(4), @as(u32, @intCast(err_names.len)), endian);
+ mem.writeInt(u32, try code.addManyAsArray(4), @intCast(err_names.len), endian);
var offset = code.items.len;
try code.resize((1 + err_names.len + 1) * 4);
for (err_names) |err_name_nts| {
- const err_name = zcu.intern_pool.stringToSlice(err_name_nts);
- mem.writeInt(u32, code.items[offset..][0..4], @as(u32, @intCast(code.items.len)), endian);
+ const err_name = err_name_nts.toSlice(ip);
+ mem.writeInt(u32, code.items[offset..][0..4], @intCast(code.items.len), endian);
offset += 4;
try code.ensureUnusedCapacity(err_name.len + 1);
code.appendSliceAssumeCapacity(err_name);
code.appendAssumeCapacity(0);
}
- mem.writeInt(u32, code.items[offset..][0..4], @as(u32, @intCast(code.items.len)), endian);
+ mem.writeInt(u32, code.items[offset..][0..4], @intCast(code.items.len), endian);
return Result.ok;
} else if (lazy_sym.ty.zigTypeTag(zcu) == .Enum) {
alignment.* = .@"1";
const tag_names = lazy_sym.ty.enumFields(zcu);
for (0..tag_names.len) |tag_index| {
- const tag_name = zcu.intern_pool.stringToSlice(tag_names.get(ip)[tag_index]);
+ const tag_name = tag_names.get(ip)[tag_index].toSlice(ip);
try code.ensureUnusedCapacity(tag_name.len + 1);
code.appendSliceAssumeCapacity(tag_name);
code.appendAssumeCapacity(0);
@@ -241,13 +241,13 @@ pub fn generateSymbol(
},
.err => |err| {
const int = try mod.getErrorValue(err.name);
- try code.writer().writeInt(u16, @as(u16, @intCast(int)), endian);
+ try code.writer().writeInt(u16, @intCast(int), endian);
},
.error_union => |error_union| {
const payload_ty = ty.errorUnionPayload(mod);
- const err_val = switch (error_union.val) {
- .err_name => |err_name| @as(u16, @intCast(try mod.getErrorValue(err_name))),
- .payload => @as(u16, 0),
+ const err_val: u16 = switch (error_union.val) {
+ .err_name => |err_name| @intCast(try mod.getErrorValue(err_name)),
+ .payload => 0,
};
if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
@@ -357,15 +357,13 @@ pub fn generateSymbol(
},
.aggregate => |aggregate| switch (ip.indexToKey(ty.toIntern())) {
.array_type => |array_type| switch (aggregate.storage) {
- .bytes => |bytes| try code.appendSlice(bytes),
+ .bytes => |bytes| try code.appendSlice(bytes.toSlice(array_type.lenIncludingSentinel(), ip)),
.elems, .repeated_elem => {
var index: u64 = 0;
- const len_including_sentinel =
- array_type.len + @intFromBool(array_type.sentinel != .none);
- while (index < len_including_sentinel) : (index += 1) {
+ while (index < array_type.lenIncludingSentinel()) : (index += 1) {
switch (try generateSymbol(bin_file, src_loc, Value.fromInterned(switch (aggregate.storage) {
.bytes => unreachable,
- .elems => |elems| elems[@as(usize, @intCast(index))],
+ .elems => |elems| elems[@intCast(index)],
.repeated_elem => |elem| if (index < array_type.len)
elem
else
@@ -399,7 +397,7 @@ pub fn generateSymbol(
}) {
.bool_true => true,
.bool_false => false,
- else => |elem| switch (mod.intern_pool.indexToKey(elem)) {
+ else => |elem| switch (ip.indexToKey(elem)) {
.undef => continue,
.int => |int| switch (int.storage) {
.u64 => |x| switch (x) {
@@ -420,7 +418,7 @@ pub fn generateSymbol(
}
} else {
switch (aggregate.storage) {
- .bytes => |bytes| try code.appendSlice(bytes),
+ .bytes => |bytes| try code.appendSlice(bytes.toSlice(vector_type.len, ip)),
.elems, .repeated_elem => {
var index: u64 = 0;
while (index < vector_type.len) : (index += 1) {
@@ -457,7 +455,7 @@ pub fn generateSymbol(
const field_val = switch (aggregate.storage) {
.bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{
.ty = field_ty,
- .storage = .{ .u64 = bytes[index] },
+ .storage = .{ .u64 = bytes.at(index, ip) },
} }),
.elems => |elems| elems[index],
.repeated_elem => |elem| elem,
@@ -493,7 +491,7 @@ pub fn generateSymbol(
const field_val = switch (aggregate.storage) {
.bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{
.ty = field_ty,
- .storage = .{ .u64 = bytes[index] },
+ .storage = .{ .u64 = bytes.at(index, ip) },
} }),
.elems => |elems| elems[index],
.repeated_elem => |elem| elem,
@@ -513,7 +511,7 @@ pub fn generateSymbol(
} else {
Value.fromInterned(field_val).writeToPackedMemory(Type.fromInterned(field_ty), mod, code.items[current_pos..], bits) catch unreachable;
}
- bits += @as(u16, @intCast(Type.fromInterned(field_ty).bitSize(mod)));
+ bits += @intCast(Type.fromInterned(field_ty).bitSize(mod));
}
},
.auto, .@"extern" => {
@@ -529,7 +527,7 @@ pub fn generateSymbol(
const field_val = switch (ip.indexToKey(val.toIntern()).aggregate.storage) {
.bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{
.ty = field_ty,
- .storage = .{ .u64 = bytes[field_index] },
+ .storage = .{ .u64 = bytes.at(field_index, ip) },
} }),
.elems => |elems| elems[field_index],
.repeated_elem => |elem| elem,
@@ -625,7 +623,8 @@ fn lowerParentPtr(
reloc_info: RelocInfo,
) CodeGenError!Result {
const mod = bin_file.comp.module.?;
- const ptr = mod.intern_pool.indexToKey(parent_ptr).ptr;
+ const ip = &mod.intern_pool;
+ const ptr = ip.indexToKey(parent_ptr).ptr;
return switch (ptr.addr) {
.decl => |decl| try lowerDeclRef(bin_file, src_loc, decl, code, debug_output, reloc_info),
.anon_decl => |ad| try lowerAnonDeclRef(bin_file, src_loc, ad, code, debug_output, reloc_info),
@@ -636,10 +635,10 @@ fn lowerParentPtr(
eu_payload,
code,
debug_output,
- reloc_info.offset(@as(u32, @intCast(errUnionPayloadOffset(
- Type.fromInterned(mod.intern_pool.typeOf(eu_payload)),
+ reloc_info.offset(@intCast(errUnionPayloadOffset(
+ Type.fromInterned(ip.typeOf(eu_payload)),
mod,
- )))),
+ ))),
),
.opt_payload => |opt_payload| try lowerParentPtr(
bin_file,
@@ -655,19 +654,19 @@ fn lowerParentPtr(
elem.base,
code,
debug_output,
- reloc_info.offset(@as(u32, @intCast(elem.index *
- Type.fromInterned(mod.intern_pool.typeOf(elem.base)).elemType2(mod).abiSize(mod)))),
+ reloc_info.offset(@intCast(elem.index *
+ Type.fromInterned(ip.typeOf(elem.base)).elemType2(mod).abiSize(mod))),
),
.field => |field| {
- const base_ptr_ty = mod.intern_pool.typeOf(field.base);
- const base_ty = mod.intern_pool.indexToKey(base_ptr_ty).ptr_type.child;
+ const base_ptr_ty = ip.typeOf(field.base);
+ const base_ty = ip.indexToKey(base_ptr_ty).ptr_type.child;
return lowerParentPtr(
bin_file,
src_loc,
field.base,
code,
debug_output,
- reloc_info.offset(switch (mod.intern_pool.indexToKey(base_ty)) {
+ reloc_info.offset(switch (ip.indexToKey(base_ty)) {
.ptr_type => |ptr_type| switch (ptr_type.flags.size) {
.One, .Many, .C => unreachable,
.Slice => switch (field.index) {
@@ -723,11 +722,12 @@ fn lowerAnonDeclRef(
) CodeGenError!Result {
_ = debug_output;
const zcu = lf.comp.module.?;
+ const ip = &zcu.intern_pool;
const target = lf.comp.root_mod.resolved_target.result;
const ptr_width_bytes = @divExact(target.ptrBitWidth(), 8);
const decl_val = anon_decl.val;
- const decl_ty = Type.fromInterned(zcu.intern_pool.typeOf(decl_val));
+ const decl_ty = Type.fromInterned(ip.typeOf(decl_val));
log.debug("lowerAnonDecl: ty = {}", .{decl_ty.fmt(zcu)});
const is_fn_body = decl_ty.zigTypeTag(zcu) == .Fn;
if (!is_fn_body and !decl_ty.hasRuntimeBits(zcu)) {
@@ -735,7 +735,7 @@ fn lowerAnonDeclRef(
return Result.ok;
}
- const decl_align = zcu.intern_pool.indexToKey(anon_decl.orig_ty).ptr_type.flags.alignment;
+ const decl_align = ip.indexToKey(anon_decl.orig_ty).ptr_type.flags.alignment;
const res = try lf.lowerAnonDecl(decl_val, decl_align, src_loc);
switch (res) {
.ok => {},
@@ -787,8 +787,8 @@ fn lowerDeclRef(
});
const endian = target.cpu.arch.endian();
switch (ptr_width) {
- 16 => mem.writeInt(u16, try code.addManyAsArray(2), @as(u16, @intCast(vaddr)), endian),
- 32 => mem.writeInt(u32, try code.addManyAsArray(4), @as(u32, @intCast(vaddr)), endian),
+ 16 => mem.writeInt(u16, try code.addManyAsArray(2), @intCast(vaddr), endian),
+ 32 => mem.writeInt(u32, try code.addManyAsArray(4), @intCast(vaddr), endian),
64 => mem.writeInt(u64, try code.addManyAsArray(8), vaddr, endian),
else => unreachable,
}
@@ -859,6 +859,7 @@ fn genDeclRef(
ptr_decl_index: InternPool.DeclIndex,
) CodeGenError!GenResult {
const zcu = lf.comp.module.?;
+ const ip = &zcu.intern_pool;
const ty = val.typeOf(zcu);
log.debug("genDeclRef: val = {}", .{val.fmtValue(zcu)});
@@ -869,7 +870,7 @@ fn genDeclRef(
const ptr_bits = target.ptrBitWidth();
const ptr_bytes: u64 = @divExact(ptr_bits, 8);
- const decl_index = switch (zcu.intern_pool.indexToKey(ptr_decl.val.toIntern())) {
+ const decl_index = switch (ip.indexToKey(ptr_decl.val.toIntern())) {
.func => |func| func.owner_decl,
.extern_func => |extern_func| extern_func.decl,
else => ptr_decl_index,
@@ -909,12 +910,9 @@ fn genDeclRef(
if (lf.cast(link.File.Elf)) |elf_file| {
if (is_extern) {
- const name = zcu.intern_pool.stringToSlice(decl.name);
+ const name = decl.name.toSlice(ip);
// TODO audit this
- const lib_name = if (decl.getOwnedVariable(zcu)) |ov|
- zcu.intern_pool.stringToSliceUnwrap(ov.lib_name)
- else
- null;
+ const lib_name = if (decl.getOwnedVariable(zcu)) |ov| ov.lib_name.toSlice(ip) else null;
const sym_index = try elf_file.getGlobalSymbol(name, lib_name);
elf_file.symbol(elf_file.zigObjectPtr().?.symbol(sym_index)).flags.needs_got = true;
return GenResult.mcv(.{ .load_symbol = sym_index });
@@ -927,11 +925,8 @@ fn genDeclRef(
return GenResult.mcv(.{ .load_symbol = sym.esym_index });
} else if (lf.cast(link.File.MachO)) |macho_file| {
if (is_extern) {
- const name = zcu.intern_pool.stringToSlice(decl.name);
- const lib_name = if (decl.getOwnedVariable(zcu)) |ov|
- zcu.intern_pool.stringToSliceUnwrap(ov.lib_name)
- else
- null;
+ const name = decl.name.toSlice(ip);
+ const lib_name = if (decl.getOwnedVariable(zcu)) |ov| ov.lib_name.toSlice(ip) else null;
const sym_index = try macho_file.getGlobalSymbol(name, lib_name);
macho_file.getSymbol(macho_file.getZigObject().?.symbols.items[sym_index]).flags.needs_got = true;
return GenResult.mcv(.{ .load_symbol = sym_index });
@@ -944,12 +939,9 @@ fn genDeclRef(
return GenResult.mcv(.{ .load_symbol = sym.nlist_idx });
} else if (lf.cast(link.File.Coff)) |coff_file| {
if (is_extern) {
- const name = zcu.intern_pool.stringToSlice(decl.name);
+ const name = decl.name.toSlice(ip);
// TODO audit this
- const lib_name = if (decl.getOwnedVariable(zcu)) |ov|
- zcu.intern_pool.stringToSliceUnwrap(ov.lib_name)
- else
- null;
+ const lib_name = if (decl.getOwnedVariable(zcu)) |ov| ov.lib_name.toSlice(ip) else null;
const global_index = try coff_file.getGlobalSymbol(name, lib_name);
try coff_file.need_got_table.put(gpa, global_index, {}); // needs GOT
return GenResult.mcv(.{ .load_got = link.File.Coff.global_symbol_bit | global_index });
@@ -1012,6 +1004,7 @@ pub fn genTypedValue(
owner_decl_index: InternPool.DeclIndex,
) CodeGenError!GenResult {
const zcu = lf.comp.module.?;
+ const ip = &zcu.intern_pool;
const ty = val.typeOf(zcu);
log.debug("genTypedValue: val = {}", .{val.fmtValue(zcu)});
@@ -1024,7 +1017,7 @@ pub fn genTypedValue(
const target = namespace.file_scope.mod.resolved_target.result;
const ptr_bits = target.ptrBitWidth();
- if (!ty.isSlice(zcu)) switch (zcu.intern_pool.indexToKey(val.toIntern())) {
+ if (!ty.isSlice(zcu)) switch (ip.indexToKey(val.toIntern())) {
.ptr => |ptr| switch (ptr.addr) {
.decl => |decl| return genDeclRef(lf, src_loc, val, decl),
else => {},
@@ -1041,7 +1034,7 @@ pub fn genTypedValue(
return GenResult.mcv(.{ .immediate = 0 });
},
.none => {},
- else => switch (zcu.intern_pool.indexToKey(val.toIntern())) {
+ else => switch (ip.indexToKey(val.toIntern())) {
.int => {
return GenResult.mcv(.{ .immediate = val.toUnsignedInt(zcu) });
},
@@ -1052,8 +1045,8 @@ pub fn genTypedValue(
.Int => {
const info = ty.intInfo(zcu);
if (info.bits <= ptr_bits) {
- const unsigned = switch (info.signedness) {
- .signed => @as(u64, @bitCast(val.toSignedInt(zcu))),
+ const unsigned: u64 = switch (info.signedness) {
+ .signed => @bitCast(val.toSignedInt(zcu)),
.unsigned => val.toUnsignedInt(zcu),
};
return GenResult.mcv(.{ .immediate = unsigned });
@@ -1075,7 +1068,7 @@ pub fn genTypedValue(
}
},
.Enum => {
- const enum_tag = zcu.intern_pool.indexToKey(val.toIntern()).enum_tag;
+ const enum_tag = ip.indexToKey(val.toIntern()).enum_tag;
return genTypedValue(
lf,
src_loc,
@@ -1084,7 +1077,7 @@ pub fn genTypedValue(
);
},
.ErrorSet => {
- const err_name = zcu.intern_pool.indexToKey(val.toIntern()).err.name;
+ const err_name = ip.indexToKey(val.toIntern()).err.name;
const error_index = zcu.global_error_set.getIndex(err_name).?;
return GenResult.mcv(.{ .immediate = error_index });
},
@@ -1094,7 +1087,7 @@ pub fn genTypedValue(
if (!payload_type.hasRuntimeBitsIgnoreComptime(zcu)) {
// We use the error type directly as the type.
const err_int_ty = try zcu.errorIntType();
- switch (zcu.intern_pool.indexToKey(val.toIntern()).error_union.val) {
+ switch (ip.indexToKey(val.toIntern()).error_union.val) {
.err_name => |err_name| return genTypedValue(
lf,
src_loc,