aboutsummaryrefslogtreecommitdiff
path: root/src/codegen.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/codegen.zig')
-rw-r--r--src/codegen.zig143
1 files changed, 73 insertions, 70 deletions
diff --git a/src/codegen.zig b/src/codegen.zig
index 4856eff7d8..2412b50cc1 100644
--- a/src/codegen.zig
+++ b/src/codegen.zig
@@ -510,88 +510,91 @@ pub fn generateSymbol(
}
}
},
- .struct_type => |struct_type| switch (struct_type.layout) {
- .Packed => {
- const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse
- return error.Overflow;
- const current_pos = code.items.len;
- try code.resize(current_pos + abi_size);
- var bits: u16 = 0;
-
- for (struct_type.field_types.get(ip), 0..) |field_ty, index| {
- const field_val = switch (aggregate.storage) {
- .bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{
- .ty = field_ty,
- .storage = .{ .u64 = bytes[index] },
- } }),
- .elems => |elems| elems[index],
- .repeated_elem => |elem| elem,
- };
+ .struct_type => {
+ const struct_type = ip.loadStructType(typed_value.ty.toIntern());
+ switch (struct_type.layout) {
+ .Packed => {
+ const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse
+ return error.Overflow;
+ const current_pos = code.items.len;
+ try code.resize(current_pos + abi_size);
+ var bits: u16 = 0;
+
+ for (struct_type.field_types.get(ip), 0..) |field_ty, index| {
+ const field_val = switch (aggregate.storage) {
+ .bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{
+ .ty = field_ty,
+ .storage = .{ .u64 = bytes[index] },
+ } }),
+ .elems => |elems| elems[index],
+ .repeated_elem => |elem| elem,
+ };
+
+ // pointer may point to a decl which must be marked used
+ // but can also result in a relocation. Therefore we handle those separately.
+ if (Type.fromInterned(field_ty).zigTypeTag(mod) == .Pointer) {
+ const field_size = math.cast(usize, Type.fromInterned(field_ty).abiSize(mod)) orelse
+ return error.Overflow;
+ var tmp_list = try std.ArrayList(u8).initCapacity(code.allocator, field_size);
+ defer tmp_list.deinit();
+ switch (try generateSymbol(bin_file, src_loc, .{
+ .ty = Type.fromInterned(field_ty),
+ .val = Value.fromInterned(field_val),
+ }, &tmp_list, debug_output, reloc_info)) {
+ .ok => @memcpy(code.items[current_pos..][0..tmp_list.items.len], tmp_list.items),
+ .fail => |em| return Result{ .fail = em },
+ }
+ } 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)));
+ }
+ },
+ .Auto, .Extern => {
+ const struct_begin = code.items.len;
+ const field_types = struct_type.field_types.get(ip);
+ const offsets = struct_type.offsets.get(ip);
+
+ var it = struct_type.iterateRuntimeOrder(ip);
+ while (it.next()) |field_index| {
+ const field_ty = field_types[field_index];
+ if (!Type.fromInterned(field_ty).hasRuntimeBits(mod)) continue;
+
+ const field_val = switch (ip.indexToKey(typed_value.val.toIntern()).aggregate.storage) {
+ .bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{
+ .ty = field_ty,
+ .storage = .{ .u64 = bytes[field_index] },
+ } }),
+ .elems => |elems| elems[field_index],
+ .repeated_elem => |elem| elem,
+ };
+
+ const padding = math.cast(
+ usize,
+ offsets[field_index] - (code.items.len - struct_begin),
+ ) orelse return error.Overflow;
+ if (padding > 0) try code.appendNTimes(0, padding);
- // pointer may point to a decl which must be marked used
- // but can also result in a relocation. Therefore we handle those separately.
- if (Type.fromInterned(field_ty).zigTypeTag(mod) == .Pointer) {
- const field_size = math.cast(usize, Type.fromInterned(field_ty).abiSize(mod)) orelse
- return error.Overflow;
- var tmp_list = try std.ArrayList(u8).initCapacity(code.allocator, field_size);
- defer tmp_list.deinit();
switch (try generateSymbol(bin_file, src_loc, .{
.ty = Type.fromInterned(field_ty),
.val = Value.fromInterned(field_val),
- }, &tmp_list, debug_output, reloc_info)) {
- .ok => @memcpy(code.items[current_pos..][0..tmp_list.items.len], tmp_list.items),
+ }, code, debug_output, reloc_info)) {
+ .ok => {},
.fail => |em| return Result{ .fail = em },
}
- } 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)));
- }
- },
- .Auto, .Extern => {
- const struct_begin = code.items.len;
- const field_types = struct_type.field_types.get(ip);
- const offsets = struct_type.offsets.get(ip);
-
- var it = struct_type.iterateRuntimeOrder(ip);
- while (it.next()) |field_index| {
- const field_ty = field_types[field_index];
- if (!Type.fromInterned(field_ty).hasRuntimeBits(mod)) continue;
-
- const field_val = switch (ip.indexToKey(typed_value.val.toIntern()).aggregate.storage) {
- .bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{
- .ty = field_ty,
- .storage = .{ .u64 = bytes[field_index] },
- } }),
- .elems => |elems| elems[field_index],
- .repeated_elem => |elem| elem,
- };
+
+ const size = struct_type.size(ip).*;
+ const alignment = struct_type.flagsPtr(ip).alignment.toByteUnitsOptional().?;
const padding = math.cast(
usize,
- offsets[field_index] - (code.items.len - struct_begin),
+ std.mem.alignForward(u64, size, @max(alignment, 1)) -
+ (code.items.len - struct_begin),
) orelse return error.Overflow;
if (padding > 0) try code.appendNTimes(0, padding);
-
- switch (try generateSymbol(bin_file, src_loc, .{
- .ty = Type.fromInterned(field_ty),
- .val = Value.fromInterned(field_val),
- }, code, debug_output, reloc_info)) {
- .ok => {},
- .fail => |em| return Result{ .fail = em },
- }
- }
-
- const size = struct_type.size(ip).*;
- const alignment = struct_type.flagsPtr(ip).alignment.toByteUnitsOptional().?;
-
- const padding = math.cast(
- usize,
- std.mem.alignForward(u64, size, @max(alignment, 1)) -
- (code.items.len - struct_begin),
- ) orelse return error.Overflow;
- if (padding > 0) try code.appendNTimes(0, padding);
- },
+ },
+ }
},
else => unreachable,
},