diff options
Diffstat (limited to 'src/codegen.zig')
| -rw-r--r-- | src/codegen.zig | 103 |
1 files changed, 55 insertions, 48 deletions
diff --git a/src/codegen.zig b/src/codegen.zig index a2d0f225bc..b7385887c4 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -22,6 +22,7 @@ const Type = @import("type.zig").Type; const TypedValue = @import("TypedValue.zig"); const Value = @import("value.zig").Value; const Zir = @import("Zir.zig"); +const Alignment = InternPool.Alignment; pub const Result = union(enum) { /// The `code` parameter passed to `generateSymbol` has the value ok. @@ -116,7 +117,8 @@ pub fn generateLazySymbol( bin_file: *link.File, src_loc: Module.SrcLoc, lazy_sym: link.File.LazySymbol, - alignment: *u32, + // TODO don't use an "out" parameter like this; put it in the result instead + alignment: *Alignment, code: *std.ArrayList(u8), debug_output: DebugInfoOutput, reloc_info: RelocInfo, @@ -141,7 +143,7 @@ pub fn generateLazySymbol( } if (lazy_sym.ty.isAnyError(mod)) { - alignment.* = 4; + alignment.* = .@"4"; const err_names = mod.global_error_set.keys(); mem.writeInt(u32, try code.addManyAsArray(4), @as(u32, @intCast(err_names.len)), endian); var offset = code.items.len; @@ -157,7 +159,7 @@ pub fn generateLazySymbol( mem.writeInt(u32, code.items[offset..][0..4], @as(u32, @intCast(code.items.len)), endian); return Result.ok; } else if (lazy_sym.ty.zigTypeTag(mod) == .Enum) { - alignment.* = 1; + alignment.* = .@"1"; for (lazy_sym.ty.enumFields(mod)) |tag_name_ip| { const tag_name = mod.intern_pool.stringToSlice(tag_name_ip); try code.ensureUnusedCapacity(tag_name.len + 1); @@ -273,7 +275,7 @@ pub fn generateSymbol( const abi_align = typed_value.ty.abiAlignment(mod); // error value first when its type is larger than the error union's payload - if (error_align > payload_align) { + if (error_align.order(payload_align) == .gt) { try code.writer().writeInt(u16, err_val, endian); } @@ -291,7 +293,7 @@ pub fn generateSymbol( .fail => |em| return .{ .fail = em }, } const unpadded_end = code.items.len - begin; - const padded_end = mem.alignForward(u64, unpadded_end, abi_align); + const padded_end = abi_align.forward(unpadded_end); const padding = math.cast(usize, padded_end - unpadded_end) orelse return error.Overflow; if (padding > 0) { @@ -300,11 +302,11 @@ pub fn generateSymbol( } // Payload size is larger than error set, so emit our error set last - if (error_align <= payload_align) { + if (error_align.compare(.lte, payload_align)) { const begin = code.items.len; try code.writer().writeInt(u16, err_val, endian); const unpadded_end = code.items.len - begin; - const padded_end = mem.alignForward(u64, unpadded_end, abi_align); + const padded_end = abi_align.forward(unpadded_end); const padding = math.cast(usize, padded_end - unpadded_end) orelse return error.Overflow; if (padding > 0) { @@ -474,23 +476,18 @@ pub fn generateSymbol( } } }, - .struct_type => |struct_type| { - const struct_obj = mod.structPtrUnwrap(struct_type.index).?; - - if (struct_obj.layout == .Packed) { - const fields = struct_obj.fields.values(); + .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 (fields, 0..) |field, index| { - const field_ty = field.ty; - + 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.toIntern(), + .ty = field_ty, .storage = .{ .u64 = bytes[index] }, } }), .elems => |elems| elems[index], @@ -499,48 +496,51 @@ pub fn generateSymbol( // pointer may point to a decl which must be marked used // but can also result in a relocation. Therefore we handle those separately. - if (field_ty.zigTypeTag(mod) == .Pointer) { - const field_size = math.cast(usize, field_ty.abiSize(mod)) orelse + if (field_ty.toType().zigTypeTag(mod) == .Pointer) { + const field_size = math.cast(usize, field_ty.toType().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 = field_ty, + .ty = field_ty.toType(), .val = field_val.toValue(), }, &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 { - field_val.toValue().writeToPackedMemory(field_ty, mod, code.items[current_pos..], bits) catch unreachable; + field_val.toValue().writeToPackedMemory(field_ty.toType(), mod, code.items[current_pos..], bits) catch unreachable; } - bits += @as(u16, @intCast(field_ty.bitSize(mod))); + bits += @as(u16, @intCast(field_ty.toType().bitSize(mod))); } - } else { + }, + .Auto, .Extern => { const struct_begin = code.items.len; - const fields = struct_obj.fields.values(); - - var it = typed_value.ty.iterateStructOffsets(mod); + const field_types = struct_type.field_types.get(ip); + const offsets = struct_type.offsets.get(ip); - while (it.next()) |field_offset| { - const field_ty = fields[field_offset.field].ty; - - if (!field_ty.hasRuntimeBits(mod)) continue; + var it = struct_type.iterateRuntimeOrder(ip); + while (it.next()) |field_index| { + const field_ty = field_types[field_index]; + if (!field_ty.toType().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.toIntern(), - .storage = .{ .u64 = bytes[field_offset.field] }, + .ty = field_ty, + .storage = .{ .u64 = bytes[field_index] }, } }), - .elems => |elems| elems[field_offset.field], + .elems => |elems| elems[field_index], .repeated_elem => |elem| elem, }; - const padding = math.cast(usize, field_offset.offset - (code.items.len - struct_begin)) orelse return error.Overflow; + 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); switch (try generateSymbol(bin_file, src_loc, .{ - .ty = field_ty, + .ty = field_ty.toType(), .val = field_val.toValue(), }, code, debug_output, reloc_info)) { .ok => {}, @@ -548,9 +548,16 @@ pub fn generateSymbol( } } - const padding = math.cast(usize, std.mem.alignForward(u64, it.offset, @max(it.big_align, 1)) - (code.items.len - struct_begin)) orelse return error.Overflow; + 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, }, @@ -565,7 +572,7 @@ pub fn generateSymbol( } // Check if we should store the tag first. - if (layout.tag_size > 0 and layout.tag_align >= layout.payload_align) { + if (layout.tag_size > 0 and layout.tag_align.compare(.gte, layout.payload_align)) { switch (try generateSymbol(bin_file, src_loc, .{ .ty = typed_value.ty.unionTagType(mod).?, .val = un.tag.toValue(), @@ -595,7 +602,7 @@ pub fn generateSymbol( } } - if (layout.tag_size > 0 and layout.tag_align < layout.payload_align) { + if (layout.tag_size > 0 and layout.tag_align.compare(.lt, layout.payload_align)) { switch (try generateSymbol(bin_file, src_loc, .{ .ty = union_obj.enum_tag_ty.toType(), .val = un.tag.toValue(), @@ -695,10 +702,10 @@ fn lowerParentPtr( @intCast(field.index), mod, )), - .Packed => if (mod.typeToStruct(base_type.toType())) |struct_obj| - math.divExact(u16, struct_obj.packedFieldBitOffset( - mod, - @intCast(field.index), + .Packed => if (mod.typeToStruct(base_type.toType())) |struct_type| + math.divExact(u16, mod.structPackedFieldBitOffset( + struct_type, + field.index, ), 8) catch |err| switch (err) { error.UnexpectedRemainder => 0, error.DivisionByZero => unreachable, @@ -844,12 +851,12 @@ fn genDeclRef( // TODO this feels clunky. Perhaps we should check for it in `genTypedValue`? if (tv.ty.castPtrToFn(mod)) |fn_ty| { if (mod.typeToFunc(fn_ty).?.is_generic) { - return GenResult.mcv(.{ .immediate = fn_ty.abiAlignment(mod) }); + return GenResult.mcv(.{ .immediate = fn_ty.abiAlignment(mod).toByteUnitsOptional().? }); } } else if (tv.ty.zigTypeTag(mod) == .Pointer) { const elem_ty = tv.ty.elemType2(mod); if (!elem_ty.hasRuntimeBits(mod)) { - return GenResult.mcv(.{ .immediate = elem_ty.abiAlignment(mod) }); + return GenResult.mcv(.{ .immediate = elem_ty.abiAlignment(mod).toByteUnitsOptional().? }); } } @@ -1036,10 +1043,10 @@ pub fn errUnionPayloadOffset(payload_ty: Type, mod: *Module) u64 { if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) return 0; const payload_align = payload_ty.abiAlignment(mod); const error_align = Type.anyerror.abiAlignment(mod); - if (payload_align >= error_align or !payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { + if (payload_align.compare(.gte, error_align) or !payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { return 0; } else { - return mem.alignForward(u64, Type.anyerror.abiSize(mod), payload_align); + return payload_align.forward(Type.anyerror.abiSize(mod)); } } @@ -1047,8 +1054,8 @@ pub fn errUnionErrorOffset(payload_ty: Type, mod: *Module) u64 { if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) return 0; const payload_align = payload_ty.abiAlignment(mod); const error_align = Type.anyerror.abiAlignment(mod); - if (payload_align >= error_align and payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { - return mem.alignForward(u64, payload_ty.abiSize(mod), error_align); + if (payload_align.compare(.gte, error_align) and payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { + return error_align.forward(payload_ty.abiSize(mod)); } else { return 0; } |
