diff options
Diffstat (limited to 'src/codegen.zig')
| -rw-r--r-- | src/codegen.zig | 134 |
1 files changed, 52 insertions, 82 deletions
diff --git a/src/codegen.zig b/src/codegen.zig index b45777564a..72fd975899 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -16,7 +16,8 @@ const Compilation = @import("Compilation.zig"); const ErrorMsg = Module.ErrorMsg; const InternPool = @import("InternPool.zig"); const Liveness = @import("Liveness.zig"); -const Module = @import("Module.zig"); +const Zcu = @import("Module.zig"); +const Module = Zcu; const Target = std.Target; const Type = @import("type.zig").Type; const Value = @import("Value.zig"); @@ -185,7 +186,7 @@ pub fn generateSymbol( const target = mod.getTarget(); const endian = target.cpu.arch.endian(); - log.debug("generateSymbol: val = {}", .{val.fmtValue(mod)}); + log.debug("generateSymbol: val = {}", .{val.fmtValue(mod, null)}); if (val.isUndefDeep(mod)) { const abi_size = math.cast(usize, ty.abiSize(mod)) orelse return error.Overflow; @@ -314,7 +315,7 @@ pub fn generateSymbol( }, .f128 => |f128_val| writeFloat(f128, f128_val, target, endian, try code.addManyAsArray(16)), }, - .ptr => switch (try lowerParentPtr(bin_file, src_loc, val.toIntern(), code, debug_output, reloc_info)) { + .ptr => switch (try lowerPtr(bin_file, src_loc, val.toIntern(), code, debug_output, reloc_info, 0)) { .ok => {}, .fail => |em| return .{ .fail = em }, }, @@ -614,111 +615,79 @@ pub fn generateSymbol( return .ok; } -fn lowerParentPtr( +fn lowerPtr( bin_file: *link.File, src_loc: Module.SrcLoc, - parent_ptr: InternPool.Index, + ptr_val: InternPool.Index, code: *std.ArrayList(u8), debug_output: DebugInfoOutput, reloc_info: RelocInfo, + prev_offset: u64, ) CodeGenError!Result { - const mod = bin_file.comp.module.?; - 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), - .int => |int| try generateSymbol(bin_file, src_loc, Value.fromInterned(int), code, debug_output, reloc_info), - .eu_payload => |eu_payload| try lowerParentPtr( + const zcu = bin_file.comp.module.?; + const ptr = zcu.intern_pool.indexToKey(ptr_val).ptr; + const offset: u64 = prev_offset + ptr.byte_offset; + return switch (ptr.base_addr) { + .decl => |decl| try lowerDeclRef(bin_file, src_loc, decl, code, debug_output, reloc_info, offset), + .anon_decl => |ad| try lowerAnonDeclRef(bin_file, src_loc, ad, code, debug_output, reloc_info, offset), + .int => try generateSymbol(bin_file, src_loc, try zcu.intValue(Type.usize, offset), code, debug_output, reloc_info), + .eu_payload => |eu_ptr| try lowerPtr( bin_file, src_loc, - eu_payload, - code, - debug_output, - reloc_info.offset(@intCast(errUnionPayloadOffset( - Type.fromInterned(ip.typeOf(eu_payload)), - mod, - ))), - ), - .opt_payload => |opt_payload| try lowerParentPtr( - bin_file, - src_loc, - opt_payload, + eu_ptr, code, debug_output, reloc_info, + offset + errUnionPayloadOffset( + Value.fromInterned(eu_ptr).typeOf(zcu).childType(zcu).errorUnionPayload(zcu), + zcu, + ), ), - .elem => |elem| try lowerParentPtr( + .opt_payload => |opt_ptr| try lowerPtr( bin_file, src_loc, - elem.base, + opt_ptr, code, debug_output, - reloc_info.offset(@intCast(elem.index * - Type.fromInterned(ip.typeOf(elem.base)).elemType2(mod).abiSize(mod))), + reloc_info, + offset, ), .field => |field| { - 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 (ip.indexToKey(base_ty)) { - .ptr_type => |ptr_type| switch (ptr_type.flags.size) { - .One, .Many, .C => unreachable, - .Slice => switch (field.index) { - 0 => 0, - 1 => @divExact(mod.getTarget().ptrBitWidth(), 8), - else => unreachable, - }, - }, - .struct_type, - .anon_struct_type, - .union_type, - => switch (Type.fromInterned(base_ty).containerLayout(mod)) { - .auto, .@"extern" => @intCast(Type.fromInterned(base_ty).structFieldOffset( - @intCast(field.index), - mod, - )), - .@"packed" => if (mod.typeToStruct(Type.fromInterned(base_ty))) |struct_obj| - if (Type.fromInterned(ptr.ty).ptrInfo(mod).packed_offset.host_size == 0) - @divExact(Type.fromInterned(base_ptr_ty).ptrInfo(mod) - .packed_offset.bit_offset + mod.structPackedFieldBitOffset( - struct_obj, - @intCast(field.index), - ), 8) - else - 0 - else - 0, - }, - else => unreachable, - }), - ); + const base_ptr = Value.fromInterned(field.base); + const base_ty = base_ptr.typeOf(zcu).childType(zcu); + const field_off: u64 = switch (base_ty.zigTypeTag(zcu)) { + .Pointer => off: { + assert(base_ty.isSlice(zcu)); + break :off switch (field.index) { + Value.slice_ptr_index => 0, + Value.slice_len_index => @divExact(zcu.getTarget().ptrBitWidth(), 8), + else => unreachable, + }; + }, + .Struct, .Union => switch (base_ty.containerLayout(zcu)) { + .auto => base_ty.structFieldOffset(@intCast(field.index), zcu), + .@"extern", .@"packed" => unreachable, + }, + else => unreachable, + }; + return lowerPtr(bin_file, src_loc, field.base, code, debug_output, reloc_info, offset + field_off); }, - .comptime_field, .comptime_alloc => unreachable, + .arr_elem, .comptime_field, .comptime_alloc => unreachable, }; } const RelocInfo = struct { parent_atom_index: u32, - addend: ?u32 = null, - - fn offset(ri: RelocInfo, addend: u32) RelocInfo { - return .{ .parent_atom_index = ri.parent_atom_index, .addend = (ri.addend orelse 0) + addend }; - } }; fn lowerAnonDeclRef( lf: *link.File, src_loc: Module.SrcLoc, - anon_decl: InternPool.Key.Ptr.Addr.AnonDecl, + anon_decl: InternPool.Key.Ptr.BaseAddr.AnonDecl, code: *std.ArrayList(u8), debug_output: DebugInfoOutput, reloc_info: RelocInfo, + offset: u64, ) CodeGenError!Result { _ = debug_output; const zcu = lf.comp.module.?; @@ -745,7 +714,7 @@ fn lowerAnonDeclRef( const vaddr = try lf.getAnonDeclVAddr(decl_val, .{ .parent_atom_index = reloc_info.parent_atom_index, .offset = code.items.len, - .addend = reloc_info.addend orelse 0, + .addend = @intCast(offset), }); const endian = target.cpu.arch.endian(); switch (ptr_width_bytes) { @@ -765,6 +734,7 @@ fn lowerDeclRef( code: *std.ArrayList(u8), debug_output: DebugInfoOutput, reloc_info: RelocInfo, + offset: u64, ) CodeGenError!Result { _ = src_loc; _ = debug_output; @@ -783,7 +753,7 @@ fn lowerDeclRef( const vaddr = try lf.getDeclVAddr(decl_index, .{ .parent_atom_index = reloc_info.parent_atom_index, .offset = code.items.len, - .addend = reloc_info.addend orelse 0, + .addend = @intCast(offset), }); const endian = target.cpu.arch.endian(); switch (ptr_width) { @@ -861,7 +831,7 @@ fn genDeclRef( const zcu = lf.comp.module.?; const ip = &zcu.intern_pool; const ty = val.typeOf(zcu); - log.debug("genDeclRef: val = {}", .{val.fmtValue(zcu)}); + log.debug("genDeclRef: val = {}", .{val.fmtValue(zcu, null)}); const ptr_decl = zcu.declPtr(ptr_decl_index); const namespace = zcu.namespacePtr(ptr_decl.src_namespace); @@ -966,7 +936,7 @@ fn genUnnamedConst( ) CodeGenError!GenResult { const zcu = lf.comp.module.?; const gpa = lf.comp.gpa; - log.debug("genUnnamedConst: val = {}", .{val.fmtValue(zcu)}); + log.debug("genUnnamedConst: val = {}", .{val.fmtValue(zcu, null)}); const local_sym_index = lf.lowerUnnamedConst(val, owner_decl_index) catch |err| { return GenResult.fail(gpa, src_loc, "lowering unnamed constant failed: {s}", .{@errorName(err)}); @@ -1007,7 +977,7 @@ pub fn genTypedValue( const ip = &zcu.intern_pool; const ty = val.typeOf(zcu); - log.debug("genTypedValue: val = {}", .{val.fmtValue(zcu)}); + log.debug("genTypedValue: val = {}", .{val.fmtValue(zcu, null)}); if (val.isUndef(zcu)) return GenResult.mcv(.undef); @@ -1018,7 +988,7 @@ pub fn genTypedValue( const ptr_bits = target.ptrBitWidth(); if (!ty.isSlice(zcu)) switch (ip.indexToKey(val.toIntern())) { - .ptr => |ptr| switch (ptr.addr) { + .ptr => |ptr| if (ptr.byte_offset == 0) switch (ptr.base_addr) { .decl => |decl| return genDeclRef(lf, src_loc, val, decl), else => {}, }, |
