| author | |
| committer | |
| log | 7d224516c4414015186bc1497ca6641b7390bf92 |
| tree | aa703daf59107ff10601ad1c626ff9c18ea11a0c |
| parent | c5822879a1da97e6c381c6684f4b9281400e5de0 |
5 files changed, 601 insertions(+), 353 deletions(-)
src/arch/wasm/Emit.zig+8-8| ... | @@ -108,7 +108,7 @@ pub fn lowerToCode(emit: *Emit) Error!void { | ... | @@ -108,7 +108,7 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 108 | try wasm.out_relocs.append(gpa, .{ | 108 | try wasm.out_relocs.append(gpa, .{ |
| 109 | .offset = @intCast(code.items.len), | 109 | .offset = @intCast(code.items.len), |
| 110 | .pointee = .{ .symbol_index = try wasm.errorNameTableSymbolIndex() }, | 110 | .pointee = .{ .symbol_index = try wasm.errorNameTableSymbolIndex() }, |
| 111 | .tag = if (is_wasm32) .MEMORY_ADDR_LEB else .MEMORY_ADDR_LEB64, | 111 | .tag = if (is_wasm32) .memory_addr_leb else .memory_addr_leb64, |
| 112 | .addend = 0, | 112 | .addend = 0, |
| 113 | }); | 113 | }); |
| 114 | code.appendNTimesAssumeCapacity(0, if (is_wasm32) 5 else 10); | 114 | code.appendNTimesAssumeCapacity(0, if (is_wasm32) 5 else 10); |
| ... | @@ -162,7 +162,7 @@ pub fn lowerToCode(emit: *Emit) Error!void { | ... | @@ -162,7 +162,7 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 162 | try wasm.out_relocs.append(gpa, .{ | 162 | try wasm.out_relocs.append(gpa, .{ |
| 163 | .offset = @intCast(code.items.len), | 163 | .offset = @intCast(code.items.len), |
| 164 | .pointee = .{ .symbol_index = try wasm.navSymbolIndex(datas[inst].nav_index) }, | 164 | .pointee = .{ .symbol_index = try wasm.navSymbolIndex(datas[inst].nav_index) }, |
| 165 | .tag = .FUNCTION_INDEX_LEB, | 165 | .tag = .function_index_leb, |
| 166 | .addend = 0, | 166 | .addend = 0, |
| 167 | }); | 167 | }); |
| 168 | code.appendNTimesAssumeCapacity(0, 5); | 168 | code.appendNTimesAssumeCapacity(0, 5); |
| ... | @@ -182,7 +182,7 @@ pub fn lowerToCode(emit: *Emit) Error!void { | ... | @@ -182,7 +182,7 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 182 | try wasm.out_relocs.append(gpa, .{ | 182 | try wasm.out_relocs.append(gpa, .{ |
| 183 | .offset = @intCast(code.items.len), | 183 | .offset = @intCast(code.items.len), |
| 184 | .pointee = .{ .type_index = func_ty_index }, | 184 | .pointee = .{ .type_index = func_ty_index }, |
| 185 | .tag = .TYPE_INDEX_LEB, | 185 | .tag = .type_index_leb, |
| 186 | .addend = 0, | 186 | .addend = 0, |
| 187 | }); | 187 | }); |
| 188 | code.appendNTimesAssumeCapacity(0, 5); | 188 | code.appendNTimesAssumeCapacity(0, 5); |
| ... | @@ -202,7 +202,7 @@ pub fn lowerToCode(emit: *Emit) Error!void { | ... | @@ -202,7 +202,7 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 202 | try wasm.out_relocs.append(gpa, .{ | 202 | try wasm.out_relocs.append(gpa, .{ |
| 203 | .offset = @intCast(code.items.len), | 203 | .offset = @intCast(code.items.len), |
| 204 | .pointee = .{ .symbol_index = try wasm.tagNameSymbolIndex(datas[inst].ip_index) }, | 204 | .pointee = .{ .symbol_index = try wasm.tagNameSymbolIndex(datas[inst].ip_index) }, |
| 205 | .tag = .FUNCTION_INDEX_LEB, | 205 | .tag = .function_index_leb, |
| 206 | .addend = 0, | 206 | .addend = 0, |
| 207 | }); | 207 | }); |
| 208 | code.appendNTimesAssumeCapacity(0, 5); | 208 | code.appendNTimesAssumeCapacity(0, 5); |
| ... | @@ -226,7 +226,7 @@ pub fn lowerToCode(emit: *Emit) Error!void { | ... | @@ -226,7 +226,7 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 226 | try wasm.out_relocs.append(gpa, .{ | 226 | try wasm.out_relocs.append(gpa, .{ |
| 227 | .offset = @intCast(code.items.len), | 227 | .offset = @intCast(code.items.len), |
| 228 | .pointee = .{ .symbol_index = try wasm.symbolNameIndex(symbol_name) }, | 228 | .pointee = .{ .symbol_index = try wasm.symbolNameIndex(symbol_name) }, |
| 229 | .tag = .FUNCTION_INDEX_LEB, | 229 | .tag = .function_index_leb, |
| 230 | .addend = 0, | 230 | .addend = 0, |
| 231 | }); | 231 | }); |
| 232 | code.appendNTimesAssumeCapacity(0, 5); | 232 | code.appendNTimesAssumeCapacity(0, 5); |
| ... | @@ -245,7 +245,7 @@ pub fn lowerToCode(emit: *Emit) Error!void { | ... | @@ -245,7 +245,7 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 245 | try wasm.out_relocs.append(gpa, .{ | 245 | try wasm.out_relocs.append(gpa, .{ |
| 246 | .offset = @intCast(code.items.len), | 246 | .offset = @intCast(code.items.len), |
| 247 | .pointee = .{ .symbol_index = try wasm.stackPointerSymbolIndex() }, | 247 | .pointee = .{ .symbol_index = try wasm.stackPointerSymbolIndex() }, |
| 248 | .tag = .GLOBAL_INDEX_LEB, | 248 | .tag = .global_index_leb, |
| 249 | .addend = 0, | 249 | .addend = 0, |
| 250 | }); | 250 | }); |
| 251 | code.appendNTimesAssumeCapacity(0, 5); | 251 | code.appendNTimesAssumeCapacity(0, 5); |
| ... | @@ -922,7 +922,7 @@ fn uavRefOffObj(wasm: *Wasm, code: *std.ArrayListUnmanaged(u8), data: Mir.UavRef | ... | @@ -922,7 +922,7 @@ fn uavRefOffObj(wasm: *Wasm, code: *std.ArrayListUnmanaged(u8), data: Mir.UavRef |
| 922 | try wasm.out_relocs.append(gpa, .{ | 922 | try wasm.out_relocs.append(gpa, .{ |
| 923 | .offset = @intCast(code.items.len), | 923 | .offset = @intCast(code.items.len), |
| 924 | .pointee = .{ .symbol_index = try wasm.uavSymbolIndex(data.uav_obj.key(wasm).*) }, | 924 | .pointee = .{ .symbol_index = try wasm.uavSymbolIndex(data.uav_obj.key(wasm).*) }, |
| 925 | .tag = if (is_wasm32) .MEMORY_ADDR_LEB else .MEMORY_ADDR_LEB64, | 925 | .tag = if (is_wasm32) .memory_addr_leb else .memory_addr_leb64, |
| 926 | .addend = data.offset, | 926 | .addend = data.offset, |
| 927 | }); | 927 | }); |
| 928 | code.appendNTimesAssumeCapacity(0, if (is_wasm32) 5 else 10); | 928 | code.appendNTimesAssumeCapacity(0, if (is_wasm32) 5 else 10); |
| ... | @@ -957,7 +957,7 @@ fn navRefOff(wasm: *Wasm, code: *std.ArrayListUnmanaged(u8), data: Mir.NavRefOff | ... | @@ -957,7 +957,7 @@ fn navRefOff(wasm: *Wasm, code: *std.ArrayListUnmanaged(u8), data: Mir.NavRefOff |
| 957 | try wasm.out_relocs.append(gpa, .{ | 957 | try wasm.out_relocs.append(gpa, .{ |
| 958 | .offset = @intCast(code.items.len), | 958 | .offset = @intCast(code.items.len), |
| 959 | .pointee = .{ .symbol_index = try wasm.navSymbolIndex(data.nav_index) }, | 959 | .pointee = .{ .symbol_index = try wasm.navSymbolIndex(data.nav_index) }, |
| 960 | .tag = if (is_wasm32) .MEMORY_ADDR_LEB else .MEMORY_ADDR_LEB64, | 960 | .tag = if (is_wasm32) .memory_addr_leb else .memory_addr_leb64, |
| 961 | .addend = data.offset, | 961 | .addend = data.offset, |
| 962 | }); | 962 | }); |
| 963 | code.appendNTimesAssumeCapacity(0, if (is_wasm32) 5 else 10); | 963 | code.appendNTimesAssumeCapacity(0, if (is_wasm32) 5 else 10); |
src/codegen.zig+2-2| ... | @@ -670,7 +670,7 @@ fn lowerUavRef( | ... | @@ -670,7 +670,7 @@ fn lowerUavRef( |
| 670 | try wasm.out_relocs.append(gpa, .{ | 670 | try wasm.out_relocs.append(gpa, .{ |
| 671 | .offset = @intCast(code.items.len), | 671 | .offset = @intCast(code.items.len), |
| 672 | .pointee = .{ .symbol_index = try wasm.uavSymbolIndex(uav.val) }, | 672 | .pointee = .{ .symbol_index = try wasm.uavSymbolIndex(uav.val) }, |
| 673 | .tag = if (ptr_width_bytes == 4) .MEMORY_ADDR_I32 else .MEMORY_ADDR_I64, | 673 | .tag = if (ptr_width_bytes == 4) .memory_addr_i32 else .memory_addr_i64, |
| 674 | .addend = @intCast(offset), | 674 | .addend = @intCast(offset), |
| 675 | }); | 675 | }); |
| 676 | } else { | 676 | } else { |
| ... | @@ -742,7 +742,7 @@ fn lowerNavRef( | ... | @@ -742,7 +742,7 @@ fn lowerNavRef( |
| 742 | try wasm.out_relocs.append(gpa, .{ | 742 | try wasm.out_relocs.append(gpa, .{ |
| 743 | .offset = @intCast(code.items.len), | 743 | .offset = @intCast(code.items.len), |
| 744 | .pointee = .{ .symbol_index = try wasm.navSymbolIndex(nav_index) }, | 744 | .pointee = .{ .symbol_index = try wasm.navSymbolIndex(nav_index) }, |
| 745 | .tag = if (ptr_width_bytes == 4) .MEMORY_ADDR_I32 else .MEMORY_ADDR_I64, | 745 | .tag = if (ptr_width_bytes == 4) .memory_addr_i32 else .memory_addr_i64, |
| 746 | .addend = @intCast(offset), | 746 | .addend = @intCast(offset), |
| 747 | }); | 747 | }); |
| 748 | } else { | 748 | } else { |
src/link/Wasm.zig+385-130| ... | @@ -93,13 +93,13 @@ func_types: std.AutoArrayHashMapUnmanaged(FunctionType, void) = .empty, | ... | @@ -93,13 +93,13 @@ func_types: std.AutoArrayHashMapUnmanaged(FunctionType, void) = .empty, |
| 93 | /// Local functions may be unnamed. | 93 | /// Local functions may be unnamed. |
| 94 | object_function_imports: std.AutoArrayHashMapUnmanaged(String, FunctionImport) = .empty, | 94 | object_function_imports: std.AutoArrayHashMapUnmanaged(String, FunctionImport) = .empty, |
| 95 | /// All functions for all objects. | 95 | /// All functions for all objects. |
| 96 | object_functions: std.ArrayListUnmanaged(Function) = .empty, | 96 | object_functions: std.ArrayListUnmanaged(ObjectFunction) = .empty, |
| 97 | 97 | ||
| 98 | /// Provides a mapping of both imports and provided globals to symbol name. | 98 | /// Provides a mapping of both imports and provided globals to symbol name. |
| 99 | /// Local globals may be unnamed. | 99 | /// Local globals may be unnamed. |
| 100 | object_global_imports: std.AutoArrayHashMapUnmanaged(String, GlobalImport) = .empty, | 100 | object_global_imports: std.AutoArrayHashMapUnmanaged(String, GlobalImport) = .empty, |
| 101 | /// All globals for all objects. | 101 | /// All globals for all objects. |
| 102 | object_globals: std.ArrayListUnmanaged(Global) = .empty, | 102 | object_globals: std.ArrayListUnmanaged(ObjectGlobal) = .empty, |
| 103 | 103 | ||
| 104 | /// All table imports for all objects. | 104 | /// All table imports for all objects. |
| 105 | object_table_imports: std.AutoArrayHashMapUnmanaged(String, TableImport) = .empty, | 105 | object_table_imports: std.AutoArrayHashMapUnmanaged(String, TableImport) = .empty, |
| ... | @@ -386,7 +386,7 @@ pub const GlobalIndex = enum(u32) { | ... | @@ -386,7 +386,7 @@ pub const GlobalIndex = enum(u32) { |
| 386 | pub const stack_pointer: GlobalIndex = @enumFromInt(0); | 386 | pub const stack_pointer: GlobalIndex = @enumFromInt(0); |
| 387 | 387 | ||
| 388 | /// Same as `stack_pointer` but with a safety assertion. | 388 | /// Same as `stack_pointer` but with a safety assertion. |
| 389 | pub fn stackPointer(wasm: *const Wasm) Global.Index { | 389 | pub fn stackPointer(wasm: *const Wasm) ObjectGlobal.Index { |
| 390 | const comp = wasm.base.comp; | 390 | const comp = wasm.base.comp; |
| 391 | assert(comp.config.output_mode != .Obj); | 391 | assert(comp.config.output_mode != .Obj); |
| 392 | assert(comp.zcu != null); | 392 | assert(comp.zcu != null); |
| ... | @@ -513,26 +513,19 @@ pub const SymbolFlags = packed struct(u32) { | ... | @@ -513,26 +513,19 @@ pub const SymbolFlags = packed struct(u32) { |
| 513 | 513 | ||
| 514 | // Above here matches the tooling conventions ABI. | 514 | // Above here matches the tooling conventions ABI. |
| 515 | 515 | ||
| 516 | padding1: u5 = 0, | 516 | padding1: u13 = 0, |
| 517 | /// Zig-specific. Dead things are allowed to be garbage collected. | 517 | /// Zig-specific. Dead things are allowed to be garbage collected. |
| 518 | alive: bool = false, | 518 | alive: bool = false, |
| 519 | /// Zig-specific. Segments only. Signals that the segment contains only | ||
| 520 | /// null terminated strings allowing the linker to perform merging. | ||
| 521 | strings: bool = false, | ||
| 522 | /// Zig-specific. This symbol comes from an object that must be included in | 519 | /// Zig-specific. This symbol comes from an object that must be included in |
| 523 | /// the final link. | 520 | /// the final link. |
| 524 | must_link: bool = false, | 521 | must_link: bool = false, |
| 525 | /// Zig-specific. Data segments only. | 522 | /// Zig-specific. |
| 526 | is_passive: bool = false, | ||
| 527 | /// Zig-specific. Data segments only. | ||
| 528 | alignment: Alignment = .none, | ||
| 529 | /// Zig-specific. Globals only. | ||
| 530 | global_type: GlobalType4 = .zero, | 523 | global_type: GlobalType4 = .zero, |
| 531 | /// Zig-specific. Tables only. | 524 | /// Zig-specific. |
| 532 | limits_has_max: bool = false, | 525 | limits_has_max: bool = false, |
| 533 | /// Zig-specific. Tables only. | 526 | /// Zig-specific. |
| 534 | limits_is_shared: bool = false, | 527 | limits_is_shared: bool = false, |
| 535 | /// Zig-specific. Tables only. | 528 | /// Zig-specific. |
| 536 | ref_type: RefType1 = .funcref, | 529 | ref_type: RefType1 = .funcref, |
| 537 | 530 | ||
| 538 | pub const Binding = enum(u2) { | 531 | pub const Binding = enum(u2) { |
| ... | @@ -554,10 +547,7 @@ pub const SymbolFlags = packed struct(u32) { | ... | @@ -554,10 +547,7 @@ pub const SymbolFlags = packed struct(u32) { |
| 554 | pub fn initZigSpecific(flags: *SymbolFlags, must_link: bool, no_strip: bool) void { | 547 | pub fn initZigSpecific(flags: *SymbolFlags, must_link: bool, no_strip: bool) void { |
| 555 | flags.no_strip = no_strip; | 548 | flags.no_strip = no_strip; |
| 556 | flags.alive = false; | 549 | flags.alive = false; |
| 557 | flags.strings = false; | ||
| 558 | flags.must_link = must_link; | 550 | flags.must_link = must_link; |
| 559 | flags.is_passive = false; | ||
| 560 | flags.alignment = .none; | ||
| 561 | flags.global_type = .zero; | 551 | flags.global_type = .zero; |
| 562 | flags.limits_has_max = false; | 552 | flags.limits_has_max = false; |
| 563 | flags.limits_is_shared = false; | 553 | flags.limits_is_shared = false; |
| ... | @@ -603,7 +593,7 @@ pub const GlobalType4 = packed struct(u4) { | ... | @@ -603,7 +593,7 @@ pub const GlobalType4 = packed struct(u4) { |
| 603 | 593 | ||
| 604 | pub const zero: GlobalType4 = @bitCast(@as(u4, 0)); | 594 | pub const zero: GlobalType4 = @bitCast(@as(u4, 0)); |
| 605 | 595 | ||
| 606 | pub fn to(gt: GlobalType4) Global.Type { | 596 | pub fn to(gt: GlobalType4) ObjectGlobal.Type { |
| 607 | return .{ | 597 | return .{ |
| 608 | .valtype = gt.valtype.to(), | 598 | .valtype = gt.valtype.to(), |
| 609 | .mutable = gt.mutable, | 599 | .mutable = gt.mutable, |
| ... | @@ -1001,18 +991,24 @@ pub const FunctionImport = extern struct { | ... | @@ -1001,18 +991,24 @@ pub const FunctionImport = extern struct { |
| 1001 | }; | 991 | }; |
| 1002 | }; | 992 | }; |
| 1003 | 993 | ||
| 1004 | pub const Function = extern struct { | 994 | pub const ObjectFunction = extern struct { |
| 1005 | flags: SymbolFlags, | 995 | flags: SymbolFlags, |
| 1006 | /// `none` if this function has no symbol describing it. | 996 | /// `none` if this function has no symbol describing it. |
| 1007 | name: OptionalString, | 997 | name: OptionalString, |
| 1008 | type_index: FunctionType.Index, | 998 | type_index: FunctionType.Index, |
| 1009 | code: Code, | 999 | code: Code, |
| 1010 | /// The offset within the section where the data starts. | 1000 | /// The offset within the code section where the data starts. |
| 1011 | offset: u32, | 1001 | offset: u32, |
| 1012 | section_index: ObjectSectionIndex, | 1002 | /// The object file whose code section contains this function. |
| 1013 | source_location: SourceLocation, | 1003 | object_index: ObjectIndex, |
| 1014 | 1004 | ||
| 1015 | pub const Code = DataPayload; | 1005 | pub const Code = DataPayload; |
| 1006 | |||
| 1007 | fn relocations(of: *const ObjectFunction, wasm: *const Wasm) ObjectRelocation.IterableSlice { | ||
| 1008 | const code_section_index = of.object_index.ptr(wasm).code_section_index.?; | ||
| 1009 | const relocs = wasm.object_relocations_table.get(code_section_index) orelse return .empty; | ||
| 1010 | return .init(relocs, of.offset, of.code.len, wasm); | ||
| 1011 | } | ||
| 1016 | }; | 1012 | }; |
| 1017 | 1013 | ||
| 1018 | pub const GlobalImport = extern struct { | 1014 | pub const GlobalImport = extern struct { |
| ... | @@ -1101,6 +1097,10 @@ pub const GlobalImport = extern struct { | ... | @@ -1101,6 +1097,10 @@ pub const GlobalImport = extern struct { |
| 1101 | }); | 1097 | }); |
| 1102 | } | 1098 | } |
| 1103 | 1099 | ||
| 1100 | fn fromObjectGlobal(wasm: *const Wasm, object_global: ObjectGlobalIndex) Resolution { | ||
| 1101 | return pack(wasm, .{ .object_global = object_global }); | ||
| 1102 | } | ||
| 1103 | |||
| 1104 | pub fn name(r: Resolution, wasm: *const Wasm) ?[]const u8 { | 1104 | pub fn name(r: Resolution, wasm: *const Wasm) ?[]const u8 { |
| 1105 | return switch (unpack(r, wasm)) { | 1105 | return switch (unpack(r, wasm)) { |
| 1106 | .unresolved => unreachable, | 1106 | .unresolved => unreachable, |
| ... | @@ -1137,22 +1137,32 @@ pub const GlobalImport = extern struct { | ... | @@ -1137,22 +1137,32 @@ pub const GlobalImport = extern struct { |
| 1137 | return index.value(wasm).module_name; | 1137 | return index.value(wasm).module_name; |
| 1138 | } | 1138 | } |
| 1139 | 1139 | ||
| 1140 | pub fn globalType(index: Index, wasm: *const Wasm) Global.Type { | 1140 | pub fn globalType(index: Index, wasm: *const Wasm) ObjectGlobal.Type { |
| 1141 | return value(index, wasm).flags.global_type.to(); | 1141 | return value(index, wasm).flags.global_type.to(); |
| 1142 | } | 1142 | } |
| 1143 | }; | 1143 | }; |
| 1144 | }; | 1144 | }; |
| 1145 | 1145 | ||
| 1146 | pub const Global = extern struct { | 1146 | pub const ObjectGlobal = extern struct { |
| 1147 | /// `none` if this function has no symbol describing it. | 1147 | /// `none` if this function has no symbol describing it. |
| 1148 | name: OptionalString, | 1148 | name: OptionalString, |
| 1149 | flags: SymbolFlags, | 1149 | flags: SymbolFlags, |
| 1150 | expr: Expr, | 1150 | expr: Expr, |
| 1151 | /// The object file whose global section contains this global. | ||
| 1152 | object_index: ObjectIndex, | ||
| 1153 | offset: u32, | ||
| 1154 | size: u32, | ||
| 1151 | 1155 | ||
| 1152 | pub const Type = struct { | 1156 | pub const Type = struct { |
| 1153 | valtype: std.wasm.Valtype, | 1157 | valtype: std.wasm.Valtype, |
| 1154 | mutable: bool, | 1158 | mutable: bool, |
| 1155 | }; | 1159 | }; |
| 1160 | |||
| 1161 | fn relocations(og: *const ObjectGlobal, wasm: *const Wasm) ObjectRelocation.IterableSlice { | ||
| 1162 | const global_section_index = og.object_index.ptr(wasm).global_section_index.?; | ||
| 1163 | const relocs = wasm.object_relocations_table.get(global_section_index) orelse return .empty; | ||
| 1164 | return .init(relocs, og.offset, og.size, wasm); | ||
| 1165 | } | ||
| 1156 | }; | 1166 | }; |
| 1157 | 1167 | ||
| 1158 | pub const RefType1 = enum(u1) { | 1168 | pub const RefType1 = enum(u1) { |
| ... | @@ -1205,6 +1215,18 @@ pub const TableImport = extern struct { | ... | @@ -1205,6 +1215,18 @@ pub const TableImport = extern struct { |
| 1205 | }; | 1215 | }; |
| 1206 | } | 1216 | } |
| 1207 | 1217 | ||
| 1218 | fn pack(unpacked: Unpacked) Resolution { | ||
| 1219 | return switch (unpacked) { | ||
| 1220 | .unresolved => .unresolved, | ||
| 1221 | .__indirect_function_table => .__indirect_function_table, | ||
| 1222 | .object_table => |i| @enumFromInt(first_object_table + @intFromEnum(i)), | ||
| 1223 | }; | ||
| 1224 | } | ||
| 1225 | |||
| 1226 | fn fromObjectTable(object_table: ObjectTableIndex) Resolution { | ||
| 1227 | return pack(.{ .object_table = object_table }); | ||
| 1228 | } | ||
| 1229 | |||
| 1208 | pub fn refType(r: Resolution, wasm: *const Wasm) std.wasm.RefType { | 1230 | pub fn refType(r: Resolution, wasm: *const Wasm) std.wasm.RefType { |
| 1209 | return switch (unpack(r)) { | 1231 | return switch (unpack(r)) { |
| 1210 | .unresolved => unreachable, | 1232 | .unresolved => unreachable, |
| ... | @@ -1298,7 +1320,7 @@ pub const ObjectTableIndex = enum(u32) { | ... | @@ -1298,7 +1320,7 @@ pub const ObjectTableIndex = enum(u32) { |
| 1298 | pub const ObjectGlobalIndex = enum(u32) { | 1320 | pub const ObjectGlobalIndex = enum(u32) { |
| 1299 | _, | 1321 | _, |
| 1300 | 1322 | ||
| 1301 | pub fn ptr(index: ObjectGlobalIndex, wasm: *const Wasm) *Global { | 1323 | pub fn ptr(index: ObjectGlobalIndex, wasm: *const Wasm) *ObjectGlobal { |
| 1302 | return &wasm.object_globals.items[@intFromEnum(index)]; | 1324 | return &wasm.object_globals.items[@intFromEnum(index)]; |
| 1303 | } | 1325 | } |
| 1304 | 1326 | ||
| ... | @@ -1338,7 +1360,7 @@ pub const ObjectMemory = extern struct { | ... | @@ -1338,7 +1360,7 @@ pub const ObjectMemory = extern struct { |
| 1338 | pub const ObjectFunctionIndex = enum(u32) { | 1360 | pub const ObjectFunctionIndex = enum(u32) { |
| 1339 | _, | 1361 | _, |
| 1340 | 1362 | ||
| 1341 | pub fn ptr(index: ObjectFunctionIndex, wasm: *const Wasm) *Function { | 1363 | pub fn ptr(index: ObjectFunctionIndex, wasm: *const Wasm) *ObjectFunction { |
| 1342 | return &wasm.object_functions.items[@intFromEnum(index)]; | 1364 | return &wasm.object_functions.items[@intFromEnum(index)]; |
| 1343 | } | 1365 | } |
| 1344 | 1366 | ||
| ... | @@ -1363,8 +1385,28 @@ pub const OptionalObjectFunctionIndex = enum(u32) { | ... | @@ -1363,8 +1385,28 @@ pub const OptionalObjectFunctionIndex = enum(u32) { |
| 1363 | pub const ObjectDataSegment = extern struct { | 1385 | pub const ObjectDataSegment = extern struct { |
| 1364 | /// `none` if segment info custom subsection is missing. | 1386 | /// `none` if segment info custom subsection is missing. |
| 1365 | name: OptionalString, | 1387 | name: OptionalString, |
| 1366 | flags: SymbolFlags, | 1388 | flags: Flags, |
| 1367 | payload: DataPayload, | 1389 | payload: DataPayload, |
| 1390 | offset: u32, | ||
| 1391 | object_index: ObjectIndex, | ||
| 1392 | |||
| 1393 | pub const Flags = packed struct(u32) { | ||
| 1394 | alive: bool = false, | ||
| 1395 | is_passive: bool = false, | ||
| 1396 | alignment: Alignment = .none, | ||
| 1397 | /// Signals that the segment contains only null terminated strings allowing | ||
| 1398 | /// the linker to perform merging. | ||
| 1399 | strings: bool = false, | ||
| 1400 | /// The segment contains thread-local data. This means that a unique copy | ||
| 1401 | /// of this segment will be created for each thread. | ||
| 1402 | tls: bool = false, | ||
| 1403 | /// If the object file is included in the final link, the segment should be | ||
| 1404 | /// retained in the final output regardless of whether it is used by the | ||
| 1405 | /// program. | ||
| 1406 | retain: bool = false, | ||
| 1407 | |||
| 1408 | _: u21 = 0, | ||
| 1409 | }; | ||
| 1368 | 1410 | ||
| 1369 | /// Index into `Wasm.object_data_segments`. | 1411 | /// Index into `Wasm.object_data_segments`. |
| 1370 | pub const Index = enum(u32) { | 1412 | pub const Index = enum(u32) { |
| ... | @@ -1374,6 +1416,12 @@ pub const ObjectDataSegment = extern struct { | ... | @@ -1374,6 +1416,12 @@ pub const ObjectDataSegment = extern struct { |
| 1374 | return &wasm.object_data_segments.items[@intFromEnum(i)]; | 1416 | return &wasm.object_data_segments.items[@intFromEnum(i)]; |
| 1375 | } | 1417 | } |
| 1376 | }; | 1418 | }; |
| 1419 | |||
| 1420 | fn relocations(ods: *const ObjectDataSegment, wasm: *const Wasm) ObjectRelocation.IterableSlice { | ||
| 1421 | const data_section_index = ods.object_index.ptr(wasm).data_section_index.?; | ||
| 1422 | const relocs = wasm.object_relocations_table.get(data_section_index) orelse return .empty; | ||
| 1423 | return .init(relocs, ods.offset, ods.payload.len, wasm); | ||
| 1424 | } | ||
| 1377 | }; | 1425 | }; |
| 1378 | 1426 | ||
| 1379 | /// A local or exported global const from an object file. | 1427 | /// A local or exported global const from an object file. |
| ... | @@ -1383,8 +1431,7 @@ pub const ObjectData = extern struct { | ... | @@ -1383,8 +1431,7 @@ pub const ObjectData = extern struct { |
| 1383 | offset: u32, | 1431 | offset: u32, |
| 1384 | /// May be zero. `offset + size` must be <= the segment's size. | 1432 | /// May be zero. `offset + size` must be <= the segment's size. |
| 1385 | size: u32, | 1433 | size: u32, |
| 1386 | /// `none` if no symbol describes it. | 1434 | name: String, |
| 1387 | name: OptionalString, | ||
| 1388 | flags: SymbolFlags, | 1435 | flags: SymbolFlags, |
| 1389 | 1436 | ||
| 1390 | /// Index into `Wasm.object_datas`. | 1437 | /// Index into `Wasm.object_datas`. |
| ... | @@ -1845,7 +1892,7 @@ pub const ZcuImportIndex = enum(u32) { | ... | @@ -1845,7 +1892,7 @@ pub const ZcuImportIndex = enum(u32) { |
| 1845 | return getExistingFunctionType(wasm, fn_info.cc, fn_info.param_types.get(ip), .fromInterned(fn_info.return_type), target).?; | 1892 | return getExistingFunctionType(wasm, fn_info.cc, fn_info.param_types.get(ip), .fromInterned(fn_info.return_type), target).?; |
| 1846 | } | 1893 | } |
| 1847 | 1894 | ||
| 1848 | pub fn globalType(index: ZcuImportIndex, wasm: *const Wasm) Global.Type { | 1895 | pub fn globalType(index: ZcuImportIndex, wasm: *const Wasm) ObjectGlobal.Type { |
| 1849 | _ = index; | 1896 | _ = index; |
| 1850 | _ = wasm; | 1897 | _ = wasm; |
| 1851 | unreachable; // Zig has no way to create Wasm globals yet. | 1898 | unreachable; // Zig has no way to create Wasm globals yet. |
| ... | @@ -1997,7 +2044,7 @@ pub const GlobalImportId = enum(u32) { | ... | @@ -1997,7 +2044,7 @@ pub const GlobalImportId = enum(u32) { |
| 1997 | }; | 2044 | }; |
| 1998 | } | 2045 | } |
| 1999 | 2046 | ||
| 2000 | pub fn globalType(id: GlobalImportId, wasm: *Wasm) Global.Type { | 2047 | pub fn globalType(id: GlobalImportId, wasm: *Wasm) ObjectGlobal.Type { |
| 2001 | return switch (unpack(id, wasm)) { | 2048 | return switch (unpack(id, wasm)) { |
| 2002 | inline .object_global_import, .zcu_import => |i| i.globalType(wasm), | 2049 | inline .object_global_import, .zcu_import => |i| i.globalType(wasm), |
| 2003 | }; | 2050 | }; |
| ... | @@ -2014,7 +2061,7 @@ pub const SymbolTableIndex = enum(u32) { | ... | @@ -2014,7 +2061,7 @@ pub const SymbolTableIndex = enum(u32) { |
| 2014 | }; | 2061 | }; |
| 2015 | 2062 | ||
| 2016 | pub const OutReloc = struct { | 2063 | pub const OutReloc = struct { |
| 2017 | tag: ObjectRelocation.Tag, | 2064 | tag: Object.RelocationType, |
| 2018 | offset: u32, | 2065 | offset: u32, |
| 2019 | pointee: Pointee, | 2066 | pointee: Pointee, |
| 2020 | addend: i32, | 2067 | addend: i32, |
| ... | @@ -2041,15 +2088,144 @@ pub const ObjectRelocation = struct { | ... | @@ -2041,15 +2088,144 @@ pub const ObjectRelocation = struct { |
| 2041 | /// When `offset` is zero, its position is immediately after the id and size of the section. | 2088 | /// When `offset` is zero, its position is immediately after the id and size of the section. |
| 2042 | offset: u32, | 2089 | offset: u32, |
| 2043 | pointee: Pointee, | 2090 | pointee: Pointee, |
| 2044 | /// Populated only for `MEMORY_ADDR_*`, `FUNCTION_OFFSET_I32` and `SECTION_OFFSET_I32`. | 2091 | /// Populated only for `memory_addr_*`, `function_offset_i32` and `section_offset_i32`. |
| 2045 | addend: i32, | 2092 | addend: i32, |
| 2046 | 2093 | ||
| 2094 | pub const Tag = enum(u8) { | ||
| 2095 | // These use `Pointee.function`. | ||
| 2096 | function_index_i32, | ||
| 2097 | function_index_leb, | ||
| 2098 | function_offset_i32, | ||
| 2099 | function_offset_i64, | ||
| 2100 | table_index_i32, | ||
| 2101 | table_index_i64, | ||
| 2102 | table_index_rel_sleb, | ||
| 2103 | table_index_rel_sleb64, | ||
| 2104 | table_index_sleb, | ||
| 2105 | table_index_sleb64, | ||
| 2106 | // These use `Pointee.symbol_name`. | ||
| 2107 | function_import_index_i32, | ||
| 2108 | function_import_index_leb, | ||
| 2109 | function_import_offset_i32, | ||
| 2110 | function_import_offset_i64, | ||
| 2111 | table_import_index_i32, | ||
| 2112 | table_import_index_i64, | ||
| 2113 | table_import_index_rel_sleb, | ||
| 2114 | table_import_index_rel_sleb64, | ||
| 2115 | table_import_index_sleb, | ||
| 2116 | table_import_index_sleb64, | ||
| 2117 | // These use `Pointee.global`. | ||
| 2118 | global_index_i32, | ||
| 2119 | global_index_leb, | ||
| 2120 | // These use `Pointee.symbol_name`. | ||
| 2121 | global_import_index_i32, | ||
| 2122 | global_import_index_leb, | ||
| 2123 | // These use `Pointee.data`. | ||
| 2124 | memory_addr_i32, | ||
| 2125 | memory_addr_i64, | ||
| 2126 | memory_addr_leb, | ||
| 2127 | memory_addr_leb64, | ||
| 2128 | memory_addr_locrel_i32, | ||
| 2129 | memory_addr_rel_sleb, | ||
| 2130 | memory_addr_rel_sleb64, | ||
| 2131 | memory_addr_sleb, | ||
| 2132 | memory_addr_sleb64, | ||
| 2133 | memory_addr_tls_sleb, | ||
| 2134 | memory_addr_tls_sleb64, | ||
| 2135 | // These use `Pointee.symbol_name`. | ||
| 2136 | memory_addr_import_i32, | ||
| 2137 | memory_addr_import_i64, | ||
| 2138 | memory_addr_import_leb, | ||
| 2139 | memory_addr_import_leb64, | ||
| 2140 | memory_addr_import_locrel_i32, | ||
| 2141 | memory_addr_import_rel_sleb, | ||
| 2142 | memory_addr_import_rel_sleb64, | ||
| 2143 | memory_addr_import_sleb, | ||
| 2144 | memory_addr_import_sleb64, | ||
| 2145 | memory_addr_import_tls_sleb, | ||
| 2146 | memory_addr_import_tls_sleb64, | ||
| 2147 | /// Uses `Pointee.section`. | ||
| 2148 | section_offset_i32, | ||
| 2149 | /// Uses `Pointee.table`. | ||
| 2150 | table_number_leb, | ||
| 2151 | /// Uses `Pointee.symbol_name`. | ||
| 2152 | table_import_number_leb, | ||
| 2153 | /// Uses `Pointee.type_index`. | ||
| 2154 | type_index_leb, | ||
| 2155 | |||
| 2156 | pub fn fromType(t: Object.RelocationType) Tag { | ||
| 2157 | return switch (t) { | ||
| 2158 | .event_index_leb => unreachable, | ||
| 2159 | .function_index_i32 => .function_index_i32, | ||
| 2160 | .function_index_leb => .function_index_leb, | ||
| 2161 | .function_offset_i32 => .function_offset_i32, | ||
| 2162 | .function_offset_i64 => .function_offset_i64, | ||
| 2163 | .global_index_i32 => .global_index_i32, | ||
| 2164 | .global_index_leb => .global_index_leb, | ||
| 2165 | .memory_addr_i32 => .memory_addr_i32, | ||
| 2166 | .memory_addr_i64 => .memory_addr_i64, | ||
| 2167 | .memory_addr_leb => .memory_addr_leb, | ||
| 2168 | .memory_addr_leb64 => .memory_addr_leb64, | ||
| 2169 | .memory_addr_locrel_i32 => .memory_addr_locrel_i32, | ||
| 2170 | .memory_addr_rel_sleb => .memory_addr_rel_sleb, | ||
| 2171 | .memory_addr_rel_sleb64 => .memory_addr_rel_sleb64, | ||
| 2172 | .memory_addr_sleb => .memory_addr_sleb, | ||
| 2173 | .memory_addr_sleb64 => .memory_addr_sleb64, | ||
| 2174 | .memory_addr_tls_sleb => .memory_addr_tls_sleb, | ||
| 2175 | .memory_addr_tls_sleb64 => .memory_addr_tls_sleb64, | ||
| 2176 | .section_offset_i32 => .section_offset_i32, | ||
| 2177 | .table_index_i32 => .table_index_i32, | ||
| 2178 | .table_index_i64 => .table_index_i64, | ||
| 2179 | .table_index_rel_sleb => .table_index_rel_sleb, | ||
| 2180 | .table_index_rel_sleb64 => .table_index_rel_sleb64, | ||
| 2181 | .table_index_sleb => .table_index_sleb, | ||
| 2182 | .table_index_sleb64 => .table_index_sleb64, | ||
| 2183 | .table_number_leb => .table_number_leb, | ||
| 2184 | .type_index_leb => .type_index_leb, | ||
| 2185 | }; | ||
| 2186 | } | ||
| 2187 | |||
| 2188 | pub fn fromTypeImport(t: Object.RelocationType) Tag { | ||
| 2189 | return switch (t) { | ||
| 2190 | .event_index_leb => unreachable, | ||
| 2191 | .function_index_i32 => .function_import_index_i32, | ||
| 2192 | .function_index_leb => .function_import_index_leb, | ||
| 2193 | .function_offset_i32 => .function_import_offset_i32, | ||
| 2194 | .function_offset_i64 => .function_import_offset_i64, | ||
| 2195 | .global_index_i32 => .global_import_index_i32, | ||
| 2196 | .global_index_leb => .global_import_index_leb, | ||
| 2197 | .memory_addr_i32 => .memory_addr_import_i32, | ||
| 2198 | .memory_addr_i64 => .memory_addr_import_i64, | ||
| 2199 | .memory_addr_leb => .memory_addr_import_leb, | ||
| 2200 | .memory_addr_leb64 => .memory_addr_import_leb64, | ||
| 2201 | .memory_addr_locrel_i32 => .memory_addr_import_locrel_i32, | ||
| 2202 | .memory_addr_rel_sleb => .memory_addr_import_rel_sleb, | ||
| 2203 | .memory_addr_rel_sleb64 => .memory_addr_import_rel_sleb64, | ||
| 2204 | .memory_addr_sleb => .memory_addr_import_sleb, | ||
| 2205 | .memory_addr_sleb64 => .memory_addr_import_sleb64, | ||
| 2206 | .memory_addr_tls_sleb => .memory_addr_import_tls_sleb, | ||
| 2207 | .memory_addr_tls_sleb64 => .memory_addr_import_tls_sleb64, | ||
| 2208 | .section_offset_i32 => unreachable, | ||
| 2209 | .table_index_i32 => .table_import_index_i32, | ||
| 2210 | .table_index_i64 => .table_import_index_i64, | ||
| 2211 | .table_index_rel_sleb => .table_import_index_rel_sleb, | ||
| 2212 | .table_index_rel_sleb64 => .table_import_index_rel_sleb64, | ||
| 2213 | .table_index_sleb => .table_import_index_sleb, | ||
| 2214 | .table_index_sleb64 => .table_import_index_sleb64, | ||
| 2215 | .table_number_leb => .table_import_number_leb, | ||
| 2216 | .type_index_leb => unreachable, | ||
| 2217 | }; | ||
| 2218 | } | ||
| 2219 | }; | ||
| 2220 | |||
| 2047 | pub const Pointee = union { | 2221 | pub const Pointee = union { |
| 2048 | symbol_name: String, | 2222 | symbol_name: String, |
| 2223 | data: ObjectData.Index, | ||
| 2049 | type_index: FunctionType.Index, | 2224 | type_index: FunctionType.Index, |
| 2050 | section: ObjectSectionIndex, | 2225 | section: ObjectSectionIndex, |
| 2051 | data: ObjectData.Index, | 2226 | function: ObjectFunctionIndex, |
| 2052 | function: Wasm.ObjectFunctionIndex, | 2227 | global: ObjectGlobalIndex, |
| 2228 | table: ObjectTableIndex, | ||
| 2053 | }; | 2229 | }; |
| 2054 | 2230 | ||
| 2055 | pub const Slice = extern struct { | 2231 | pub const Slice = extern struct { |
| ... | @@ -2057,63 +2233,47 @@ pub const ObjectRelocation = struct { | ... | @@ -2057,63 +2233,47 @@ pub const ObjectRelocation = struct { |
| 2057 | off: u32, | 2233 | off: u32, |
| 2058 | len: u32, | 2234 | len: u32, |
| 2059 | 2235 | ||
| 2060 | pub fn slice(s: Slice, wasm: *const Wasm) []ObjectRelocation { | 2236 | const empty: Slice = .{ .off = 0, .len = 0 }; |
| 2061 | return wasm.relocations.items[s.off..][0..s.len]; | 2237 | |
| 2238 | fn tags(s: Slice, wasm: *const Wasm) []const ObjectRelocation.Tag { | ||
| 2239 | return wasm.object_relocations.items(.tag)[s.off..][0..s.len]; | ||
| 2240 | } | ||
| 2241 | |||
| 2242 | fn offsets(s: Slice, wasm: *const Wasm) []const u32 { | ||
| 2243 | return wasm.object_relocations.items(.offset)[s.off..][0..s.len]; | ||
| 2244 | } | ||
| 2245 | |||
| 2246 | fn pointees(s: Slice, wasm: *const Wasm) []const Pointee { | ||
| 2247 | return wasm.object_relocations.items(.pointee)[s.off..][0..s.len]; | ||
| 2248 | } | ||
| 2249 | |||
| 2250 | fn addends(s: Slice, wasm: *const Wasm) []const i32 { | ||
| 2251 | return wasm.object_relocations.items(.addend)[s.off..][0..s.len]; | ||
| 2062 | } | 2252 | } |
| 2063 | }; | 2253 | }; |
| 2064 | 2254 | ||
| 2065 | pub const Tag = enum(u8) { | 2255 | pub const IterableSlice = struct { |
| 2066 | /// Uses `function`. | 2256 | slice: Slice, |
| 2067 | FUNCTION_INDEX_LEB = 0, | 2257 | /// Offset at which point to stop iterating. |
| 2068 | /// Uses `table_index`. | 2258 | end: u32, |
| 2069 | TABLE_INDEX_SLEB = 1, | 2259 | |
| 2070 | /// Uses `table_index`. | 2260 | const empty: IterableSlice = .{ .slice = .empty, .end = 0 }; |
| 2071 | TABLE_INDEX_I32 = 2, | 2261 | |
| 2072 | /// Uses `data_segment`. | 2262 | fn init(relocs: Slice, offset: u32, size: u32, wasm: *const Wasm) IterableSlice { |
| 2073 | MEMORY_ADDR_LEB = 3, | 2263 | const offsets = relocs.offsets(wasm); |
| 2074 | /// Uses `data_segment`. | 2264 | const start = std.sort.lowerBound(u32, offsets, offset, order); |
| 2075 | MEMORY_ADDR_SLEB = 4, | 2265 | return .{ |
| 2076 | /// Uses `data_segment`. | 2266 | .slice = .{ |
| 2077 | MEMORY_ADDR_I32 = 5, | 2267 | .off = @intCast(relocs.off + start), |
| 2078 | /// Uses `type_index`. | 2268 | .len = @intCast(relocs.len - start), |
| 2079 | TYPE_INDEX_LEB = 6, | 2269 | }, |
| 2080 | /// Uses `symbol_name`. | 2270 | .end = offset + size, |
| 2081 | GLOBAL_INDEX_LEB = 7, | 2271 | }; |
| 2082 | FUNCTION_OFFSET_I32 = 8, | 2272 | } |
| 2083 | SECTION_OFFSET_I32 = 9, | 2273 | |
| 2084 | TAG_INDEX_LEB = 10, | 2274 | fn order(lhs: u32, rhs: u32) std.math.Order { |
| 2085 | /// Uses `data_segment`. | 2275 | return std.math.order(lhs, rhs); |
| 2086 | MEMORY_ADDR_REL_SLEB = 11, | 2276 | } |
| 2087 | TABLE_INDEX_REL_SLEB = 12, | ||
| 2088 | /// Uses `symbol_name`. | ||
| 2089 | GLOBAL_INDEX_I32 = 13, | ||
| 2090 | /// Uses `data_segment`. | ||
| 2091 | MEMORY_ADDR_LEB64 = 14, | ||
| 2092 | /// Uses `data_segment`. | ||
| 2093 | MEMORY_ADDR_SLEB64 = 15, | ||
| 2094 | /// Uses `data_segment`. | ||
| 2095 | MEMORY_ADDR_I64 = 16, | ||
| 2096 | /// Uses `data_segment`. | ||
| 2097 | MEMORY_ADDR_REL_SLEB64 = 17, | ||
| 2098 | /// Uses `table_index`. | ||
| 2099 | TABLE_INDEX_SLEB64 = 18, | ||
| 2100 | /// Uses `table_index`. | ||
| 2101 | TABLE_INDEX_I64 = 19, | ||
| 2102 | TABLE_NUMBER_LEB = 20, | ||
| 2103 | /// Uses `data_segment`. | ||
| 2104 | MEMORY_ADDR_TLS_SLEB = 21, | ||
| 2105 | FUNCTION_OFFSET_I64 = 22, | ||
| 2106 | /// Uses `data_segment`. | ||
| 2107 | MEMORY_ADDR_LOCREL_I32 = 23, | ||
| 2108 | TABLE_INDEX_REL_SLEB64 = 24, | ||
| 2109 | /// Uses `data_segment`. | ||
| 2110 | MEMORY_ADDR_TLS_SLEB64 = 25, | ||
| 2111 | /// Uses `symbol_name`. | ||
| 2112 | FUNCTION_INDEX_I32 = 26, | ||
| 2113 | |||
| 2114 | // Above here, the tags correspond to symbol table ABI described in | ||
| 2115 | // https://github.com/WebAssembly/tool-conventions/blob/main/Linking.md | ||
| 2116 | // Below, the tags are compiler-internal. | ||
| 2117 | }; | 2277 | }; |
| 2118 | }; | 2278 | }; |
| 2119 | 2279 | ||
| ... | @@ -2781,7 +2941,7 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.File.FlushError!v | ... | @@ -2781,7 +2941,7 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.File.FlushError!v |
| 2781 | // At the end, output functions and globals will be populated. | 2941 | // At the end, output functions and globals will be populated. |
| 2782 | for (wasm.object_function_imports.keys(), wasm.object_function_imports.values(), 0..) |name, *import, i| { | 2942 | for (wasm.object_function_imports.keys(), wasm.object_function_imports.values(), 0..) |name, *import, i| { |
| 2783 | if (import.flags.isIncluded(rdynamic)) { | 2943 | if (import.flags.isIncluded(rdynamic)) { |
| 2784 | try markFunction(wasm, name, import, @enumFromInt(i)); | 2944 | try markFunctionImport(wasm, name, import, @enumFromInt(i)); |
| 2785 | } | 2945 | } |
| 2786 | } | 2946 | } |
| 2787 | wasm.functions_end_prelink = @intCast(wasm.functions.entries.len); | 2947 | wasm.functions_end_prelink = @intCast(wasm.functions.entries.len); |
| ... | @@ -2789,7 +2949,7 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.File.FlushError!v | ... | @@ -2789,7 +2949,7 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.File.FlushError!v |
| 2789 | 2949 | ||
| 2790 | for (wasm.object_global_imports.keys(), wasm.object_global_imports.values(), 0..) |name, *import, i| { | 2950 | for (wasm.object_global_imports.keys(), wasm.object_global_imports.values(), 0..) |name, *import, i| { |
| 2791 | if (import.flags.isIncluded(rdynamic)) { | 2951 | if (import.flags.isIncluded(rdynamic)) { |
| 2792 | try markGlobal(wasm, name, import, @enumFromInt(i)); | 2952 | try markGlobalImport(wasm, name, import, @enumFromInt(i)); |
| 2793 | } | 2953 | } |
| 2794 | } | 2954 | } |
| 2795 | wasm.globals_end_prelink = @intCast(wasm.globals.entries.len); | 2955 | wasm.globals_end_prelink = @intCast(wasm.globals.entries.len); |
| ... | @@ -2797,13 +2957,12 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.File.FlushError!v | ... | @@ -2797,13 +2957,12 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.File.FlushError!v |
| 2797 | 2957 | ||
| 2798 | for (wasm.object_table_imports.keys(), wasm.object_table_imports.values(), 0..) |name, *import, i| { | 2958 | for (wasm.object_table_imports.keys(), wasm.object_table_imports.values(), 0..) |name, *import, i| { |
| 2799 | if (import.flags.isIncluded(rdynamic)) { | 2959 | if (import.flags.isIncluded(rdynamic)) { |
| 2800 | try markTable(wasm, name, import, @enumFromInt(i)); | 2960 | try markTableImport(wasm, name, import, @enumFromInt(i)); |
| 2801 | } | 2961 | } |
| 2802 | } | 2962 | } |
| 2803 | } | 2963 | } |
| 2804 | 2964 | ||
| 2805 | /// Recursively mark alive everything referenced by the function. | 2965 | fn markFunctionImport( |
| 2806 | fn markFunction( | ||
| 2807 | wasm: *Wasm, | 2966 | wasm: *Wasm, |
| 2808 | name: String, | 2967 | name: String, |
| 2809 | import: *FunctionImport, | 2968 | import: *FunctionImport, |
| ... | @@ -2814,8 +2973,6 @@ fn markFunction( | ... | @@ -2814,8 +2973,6 @@ fn markFunction( |
| 2814 | 2973 | ||
| 2815 | const comp = wasm.base.comp; | 2974 | const comp = wasm.base.comp; |
| 2816 | const gpa = comp.gpa; | 2975 | const gpa = comp.gpa; |
| 2817 | const rdynamic = comp.config.rdynamic; | ||
| 2818 | const is_obj = comp.config.output_mode == .Obj; | ||
| 2819 | 2976 | ||
| 2820 | try wasm.functions.ensureUnusedCapacity(gpa, 1); | 2977 | try wasm.functions.ensureUnusedCapacity(gpa, 1); |
| 2821 | 2978 | ||
| ... | @@ -2836,20 +2993,31 @@ fn markFunction( | ... | @@ -2836,20 +2993,31 @@ fn markFunction( |
| 2836 | try wasm.function_imports.put(gpa, name, .fromObject(func_index, wasm)); | 2993 | try wasm.function_imports.put(gpa, name, .fromObject(func_index, wasm)); |
| 2837 | } | 2994 | } |
| 2838 | } else { | 2995 | } else { |
| 2839 | const gop = wasm.functions.getOrPutAssumeCapacity(import.resolution); | 2996 | try markFunction(wasm, import.resolution.unpack(wasm).object_function); |
| 2997 | } | ||
| 2998 | } | ||
| 2840 | 2999 | ||
| 2841 | if (!is_obj and import.flags.isExported(rdynamic)) try wasm.function_exports.append(gpa, .{ | 3000 | /// Recursively mark alive everything referenced by the function. |
| 2842 | .name = name, | 3001 | fn markFunction(wasm: *Wasm, i: ObjectFunctionIndex) Allocator.Error!void { |
| 2843 | .function_index = @enumFromInt(gop.index), | 3002 | const comp = wasm.base.comp; |
| 2844 | }); | 3003 | const gpa = comp.gpa; |
| 3004 | const gop = try wasm.functions.getOrPut(gpa, .fromObjectFunction(wasm, i)); | ||
| 3005 | if (gop.found_existing) return; | ||
| 2845 | 3006 | ||
| 2846 | for (try wasm.functionResolutionRelocSlice(import.resolution)) |reloc| | 3007 | const rdynamic = comp.config.rdynamic; |
| 2847 | try wasm.markReloc(reloc); | 3008 | const is_obj = comp.config.output_mode == .Obj; |
| 2848 | } | 3009 | const function = i.ptr(wasm); |
| 3010 | |||
| 3011 | if (!is_obj and function.flags.isExported(rdynamic)) try wasm.function_exports.append(gpa, .{ | ||
| 3012 | .name = function.name.unwrap().?, | ||
| 3013 | .function_index = @enumFromInt(gop.index), | ||
| 3014 | }); | ||
| 3015 | |||
| 3016 | try wasm.markRelocations(function.relocations(wasm)); | ||
| 2849 | } | 3017 | } |
| 2850 | 3018 | ||
| 2851 | /// Recursively mark alive everything referenced by the global. | 3019 | /// Recursively mark alive everything referenced by the global. |
| 2852 | fn markGlobal( | 3020 | fn markGlobalImport( |
| 2853 | wasm: *Wasm, | 3021 | wasm: *Wasm, |
| 2854 | name: String, | 3022 | name: String, |
| 2855 | import: *GlobalImport, | 3023 | import: *GlobalImport, |
| ... | @@ -2860,8 +3028,6 @@ fn markGlobal( | ... | @@ -2860,8 +3028,6 @@ fn markGlobal( |
| 2860 | 3028 | ||
| 2861 | const comp = wasm.base.comp; | 3029 | const comp = wasm.base.comp; |
| 2862 | const gpa = comp.gpa; | 3030 | const gpa = comp.gpa; |
| 2863 | const rdynamic = comp.config.rdynamic; | ||
| 2864 | const is_obj = comp.config.output_mode == .Obj; | ||
| 2865 | 3031 | ||
| 2866 | try wasm.globals.ensureUnusedCapacity(gpa, 1); | 3032 | try wasm.globals.ensureUnusedCapacity(gpa, 1); |
| 2867 | 3033 | ||
| ... | @@ -2888,19 +3054,29 @@ fn markGlobal( | ... | @@ -2888,19 +3054,29 @@ fn markGlobal( |
| 2888 | try wasm.global_imports.put(gpa, name, .fromObject(global_index, wasm)); | 3054 | try wasm.global_imports.put(gpa, name, .fromObject(global_index, wasm)); |
| 2889 | } | 3055 | } |
| 2890 | } else { | 3056 | } else { |
| 2891 | const gop = wasm.globals.getOrPutAssumeCapacity(import.resolution); | 3057 | try markGlobal(wasm, import.resolution.unpack(wasm).object_global); |
| 3058 | } | ||
| 3059 | } | ||
| 2892 | 3060 | ||
| 2893 | if (!is_obj and import.flags.isExported(rdynamic)) try wasm.global_exports.append(gpa, .{ | 3061 | fn markGlobal(wasm: *Wasm, i: ObjectGlobalIndex) Allocator.Error!void { |
| 2894 | .name = name, | 3062 | const comp = wasm.base.comp; |
| 2895 | .global_index = @enumFromInt(gop.index), | 3063 | const gpa = comp.gpa; |
| 2896 | }); | 3064 | const gop = try wasm.globals.getOrPut(gpa, .fromObjectGlobal(wasm, i)); |
| 3065 | if (gop.found_existing) return; | ||
| 2897 | 3066 | ||
| 2898 | for (try wasm.globalResolutionRelocSlice(import.resolution)) |reloc| | 3067 | const rdynamic = comp.config.rdynamic; |
| 2899 | try wasm.markReloc(reloc); | 3068 | const is_obj = comp.config.output_mode == .Obj; |
| 2900 | } | 3069 | const global = i.ptr(wasm); |
| 3070 | |||
| 3071 | if (!is_obj and global.flags.isExported(rdynamic)) try wasm.global_exports.append(gpa, .{ | ||
| 3072 | .name = global.name.unwrap().?, | ||
| 3073 | .global_index = @enumFromInt(gop.index), | ||
| 3074 | }); | ||
| 3075 | |||
| 3076 | try wasm.markRelocations(global.relocations(wasm)); | ||
| 2901 | } | 3077 | } |
| 2902 | 3078 | ||
| 2903 | fn markTable( | 3079 | fn markTableImport( |
| 2904 | wasm: *Wasm, | 3080 | wasm: *Wasm, |
| 2905 | name: String, | 3081 | name: String, |
| 2906 | import: *TableImport, | 3082 | import: *TableImport, |
| ... | @@ -2927,22 +3103,101 @@ fn markTable( | ... | @@ -2927,22 +3103,101 @@ fn markTable( |
| 2927 | } | 3103 | } |
| 2928 | } | 3104 | } |
| 2929 | 3105 | ||
| 2930 | fn globalResolutionRelocSlice(wasm: *Wasm, resolution: GlobalImport.Resolution) ![]const ObjectRelocation { | 3106 | fn markDataSegment(wasm: *Wasm, segment_index: ObjectDataSegment.Index) Allocator.Error!void { |
| 2931 | assert(resolution != .unresolved); | 3107 | const segment = segment_index.ptr(wasm); |
| 2932 | _ = wasm; | 3108 | if (segment.flags.alive) return; |
| 2933 | @panic("TODO"); | 3109 | segment.flags.alive = true; |
| 2934 | } | ||
| 2935 | 3110 | ||
| 2936 | fn functionResolutionRelocSlice(wasm: *Wasm, resolution: FunctionImport.Resolution) ![]const ObjectRelocation { | 3111 | try wasm.markRelocations(segment.relocations(wasm)); |
| 2937 | assert(resolution != .unresolved); | ||
| 2938 | _ = wasm; | ||
| 2939 | @panic("TODO"); | ||
| 2940 | } | 3112 | } |
| 2941 | 3113 | ||
| 2942 | fn markReloc(wasm: *Wasm, reloc: ObjectRelocation) !void { | 3114 | fn markRelocations(wasm: *Wasm, relocs: ObjectRelocation.IterableSlice) Allocator.Error!void { |
| 2943 | _ = wasm; | 3115 | for (relocs.slice.tags(wasm), relocs.slice.pointees(wasm), relocs.slice.offsets(wasm)) |tag, *pointee, offset| { |
| 2944 | _ = reloc; | 3116 | if (offset >= relocs.end) break; |
| 2945 | @panic("TODO"); | 3117 | switch (tag) { |
| 3118 | .function_import_index_leb, | ||
| 3119 | .function_import_index_i32, | ||
| 3120 | .function_import_offset_i32, | ||
| 3121 | .function_import_offset_i64, | ||
| 3122 | .table_import_index_sleb, | ||
| 3123 | .table_import_index_i32, | ||
| 3124 | .table_import_index_sleb64, | ||
| 3125 | .table_import_index_i64, | ||
| 3126 | .table_import_index_rel_sleb, | ||
| 3127 | .table_import_index_rel_sleb64, | ||
| 3128 | => { | ||
| 3129 | const name = pointee.symbol_name; | ||
| 3130 | const i: FunctionImport.Index = @enumFromInt(wasm.object_function_imports.getIndex(name).?); | ||
| 3131 | try markFunctionImport(wasm, name, i.value(wasm), i); | ||
| 3132 | }, | ||
| 3133 | .global_import_index_leb, .global_import_index_i32 => { | ||
| 3134 | const name = pointee.symbol_name; | ||
| 3135 | const i: GlobalImport.Index = @enumFromInt(wasm.object_global_imports.getIndex(name).?); | ||
| 3136 | try markGlobalImport(wasm, name, i.value(wasm), i); | ||
| 3137 | }, | ||
| 3138 | .table_import_number_leb => { | ||
| 3139 | const name = pointee.symbol_name; | ||
| 3140 | const i: TableImport.Index = @enumFromInt(wasm.object_table_imports.getIndex(name).?); | ||
| 3141 | try markTableImport(wasm, name, i.value(wasm), i); | ||
| 3142 | }, | ||
| 3143 | |||
| 3144 | .function_index_leb, | ||
| 3145 | .function_index_i32, | ||
| 3146 | .function_offset_i32, | ||
| 3147 | .function_offset_i64, | ||
| 3148 | .table_index_sleb, | ||
| 3149 | .table_index_i32, | ||
| 3150 | .table_index_sleb64, | ||
| 3151 | .table_index_i64, | ||
| 3152 | .table_index_rel_sleb, | ||
| 3153 | .table_index_rel_sleb64, | ||
| 3154 | => try markFunction(wasm, pointee.function), | ||
| 3155 | .global_index_leb, | ||
| 3156 | .global_index_i32, | ||
| 3157 | => try markGlobal(wasm, pointee.global), | ||
| 3158 | .table_number_leb, | ||
| 3159 | => try wasm.tables.put(wasm.base.comp.gpa, .fromObjectTable(pointee.table), {}), | ||
| 3160 | |||
| 3161 | .section_offset_i32 => { | ||
| 3162 | log.warn("TODO: ensure section {d} is included in output", .{pointee.section}); | ||
| 3163 | }, | ||
| 3164 | .memory_addr_import_leb, | ||
| 3165 | .memory_addr_import_sleb, | ||
| 3166 | .memory_addr_import_i32, | ||
| 3167 | .memory_addr_import_rel_sleb, | ||
| 3168 | .memory_addr_import_leb64, | ||
| 3169 | .memory_addr_import_sleb64, | ||
| 3170 | .memory_addr_import_i64, | ||
| 3171 | .memory_addr_import_rel_sleb64, | ||
| 3172 | .memory_addr_import_tls_sleb, | ||
| 3173 | .memory_addr_import_locrel_i32, | ||
| 3174 | .memory_addr_import_tls_sleb64, | ||
| 3175 | => { | ||
| 3176 | const name = pointee.symbol_name; | ||
| 3177 | if (name == wasm.preloaded_strings.__heap_end or | ||
| 3178 | name == wasm.preloaded_strings.__heap_base) | ||
| 3179 | { | ||
| 3180 | continue; | ||
| 3181 | } | ||
| 3182 | log.warn("TODO: ensure data symbol {s} is included in output", .{name.slice(wasm)}); | ||
| 3183 | }, | ||
| 3184 | |||
| 3185 | .memory_addr_leb, | ||
| 3186 | .memory_addr_sleb, | ||
| 3187 | .memory_addr_i32, | ||
| 3188 | .memory_addr_rel_sleb, | ||
| 3189 | .memory_addr_leb64, | ||
| 3190 | .memory_addr_sleb64, | ||
| 3191 | .memory_addr_i64, | ||
| 3192 | .memory_addr_rel_sleb64, | ||
| 3193 | .memory_addr_tls_sleb, | ||
| 3194 | .memory_addr_locrel_i32, | ||
| 3195 | .memory_addr_tls_sleb64, | ||
| 3196 | => try markDataSegment(wasm, pointee.data.ptr(wasm).segment), | ||
| 3197 | |||
| 3198 | .type_index_leb => continue, | ||
| 3199 | } | ||
| 3200 | } | ||
| 2946 | } | 3201 | } |
| 2947 | 3202 | ||
| 2948 | pub fn flushModule( | 3203 | pub fn flushModule( |
src/link/Wasm/Flush.zig-142| ... | @@ -1398,148 +1398,6 @@ fn emitSegmentInfo(wasm: *Wasm, binary_bytes: *std.ArrayList(u8)) !void { | ... | @@ -1398,148 +1398,6 @@ fn emitSegmentInfo(wasm: *Wasm, binary_bytes: *std.ArrayList(u8)) !void { |
| 1398 | // try binary_bytes.insertSlice(table_offset, &buf); | 1398 | // try binary_bytes.insertSlice(table_offset, &buf); |
| 1399 | //} | 1399 | //} |
| 1400 | 1400 | ||
| 1401 | ///// Resolves the relocations within the atom, writing the new value | ||
| 1402 | ///// at the calculated offset. | ||
| 1403 | //fn resolveAtomRelocs(wasm: *const Wasm, atom: *Atom) void { | ||
| 1404 | // const symbol_name = wasm.symbolLocName(atom.symbolLoc()); | ||
| 1405 | // log.debug("resolving {d} relocs in atom '{s}'", .{ atom.relocs.len, symbol_name }); | ||
| 1406 | // | ||
| 1407 | // for (atom.relocSlice(wasm)) |reloc| { | ||
| 1408 | // const value = atomRelocationValue(wasm, atom, reloc); | ||
| 1409 | // log.debug("relocating '{s}' referenced in '{s}' offset=0x{x:0>8} value={d}", .{ | ||
| 1410 | // wasm.symbolLocName(.{ | ||
| 1411 | // .file = atom.file, | ||
| 1412 | // .index = @enumFromInt(reloc.index), | ||
| 1413 | // }), | ||
| 1414 | // symbol_name, | ||
| 1415 | // reloc.offset, | ||
| 1416 | // value, | ||
| 1417 | // }); | ||
| 1418 | // | ||
| 1419 | // switch (reloc.tag) { | ||
| 1420 | // .TABLE_INDEX_I32, | ||
| 1421 | // .FUNCTION_OFFSET_I32, | ||
| 1422 | // .GLOBAL_INDEX_I32, | ||
| 1423 | // .MEMORY_ADDR_I32, | ||
| 1424 | // .SECTION_OFFSET_I32, | ||
| 1425 | // => mem.writeInt(u32, atom.code.slice(wasm)[reloc.offset - atom.original_offset ..][0..4], @as(u32, @truncate(value)), .little), | ||
| 1426 | // | ||
| 1427 | // .TABLE_INDEX_I64, | ||
| 1428 | // .MEMORY_ADDR_I64, | ||
| 1429 | // => mem.writeInt(u64, atom.code.slice(wasm)[reloc.offset - atom.original_offset ..][0..8], value, .little), | ||
| 1430 | // | ||
| 1431 | // .GLOBAL_INDEX_LEB, | ||
| 1432 | // .EVENT_INDEX_LEB, | ||
| 1433 | // .FUNCTION_INDEX_LEB, | ||
| 1434 | // .MEMORY_ADDR_LEB, | ||
| 1435 | // .MEMORY_ADDR_SLEB, | ||
| 1436 | // .TABLE_INDEX_SLEB, | ||
| 1437 | // .TABLE_NUMBER_LEB, | ||
| 1438 | // .TYPE_INDEX_LEB, | ||
| 1439 | // .MEMORY_ADDR_TLS_SLEB, | ||
| 1440 | // => leb.writeUnsignedFixed(5, atom.code.slice(wasm)[reloc.offset - atom.original_offset ..][0..5], @as(u32, @truncate(value))), | ||
| 1441 | // | ||
| 1442 | // .MEMORY_ADDR_LEB64, | ||
| 1443 | // .MEMORY_ADDR_SLEB64, | ||
| 1444 | // .TABLE_INDEX_SLEB64, | ||
| 1445 | // .MEMORY_ADDR_TLS_SLEB64, | ||
| 1446 | // => leb.writeUnsignedFixed(10, atom.code.slice(wasm)[reloc.offset - atom.original_offset ..][0..10], value), | ||
| 1447 | // } | ||
| 1448 | // } | ||
| 1449 | //} | ||
| 1450 | |||
| 1451 | ///// From a given `relocation` will return the new value to be written. | ||
| 1452 | ///// All values will be represented as a `u64` as all values can fit within it. | ||
| 1453 | ///// The final value must be casted to the correct size. | ||
| 1454 | //fn atomRelocationValue(wasm: *const Wasm, atom: *const Atom, relocation: *const Relocation) u64 { | ||
| 1455 | // if (relocation.tag == .TYPE_INDEX_LEB) { | ||
| 1456 | // // Eagerly resolved when parsing the object file. | ||
| 1457 | // if (true) @panic("TODO the eager resolve when parsing"); | ||
| 1458 | // return relocation.index; | ||
| 1459 | // } | ||
| 1460 | // const target_loc = wasm.symbolLocFinalLoc(.{ | ||
| 1461 | // .file = atom.file, | ||
| 1462 | // .index = @enumFromInt(relocation.index), | ||
| 1463 | // }); | ||
| 1464 | // const symbol = wasm.finalSymbolByLoc(target_loc); | ||
| 1465 | // if (symbol.tag != .section and !symbol.flags.alive) { | ||
| 1466 | // const val = atom.tombstone(wasm) orelse relocation.addend; | ||
| 1467 | // return @bitCast(val); | ||
| 1468 | // } | ||
| 1469 | // return switch (relocation.tag) { | ||
| 1470 | // .FUNCTION_INDEX_LEB => if (symbol.flags.undefined) | ||
| 1471 | // @intFromEnum(symbol.pointee.function_import) | ||
| 1472 | // else | ||
| 1473 | // @intFromEnum(symbol.pointee.function) + f.function_imports.items.len, | ||
| 1474 | // .TABLE_NUMBER_LEB => if (symbol.flags.undefined) | ||
| 1475 | // @intFromEnum(symbol.pointee.table_import) | ||
| 1476 | // else | ||
| 1477 | // @intFromEnum(symbol.pointee.table) + wasm.table_imports.items.len, | ||
| 1478 | // .TABLE_INDEX_I32, | ||
| 1479 | // .TABLE_INDEX_I64, | ||
| 1480 | // .TABLE_INDEX_SLEB, | ||
| 1481 | // .TABLE_INDEX_SLEB64, | ||
| 1482 | // => wasm.indirect_function_table.get(.{ .file = atom.file, .index = @enumFromInt(relocation.index) }) orelse 0, | ||
| 1483 | // | ||
| 1484 | // .TYPE_INDEX_LEB => unreachable, // handled above | ||
| 1485 | // .GLOBAL_INDEX_I32, .GLOBAL_INDEX_LEB => if (symbol.flags.undefined) | ||
| 1486 | // @intFromEnum(symbol.pointee.global_import) | ||
| 1487 | // else | ||
| 1488 | // @intFromEnum(symbol.pointee.global) + f.global_imports.items.len, | ||
| 1489 | // | ||
| 1490 | // .MEMORY_ADDR_I32, | ||
| 1491 | // .MEMORY_ADDR_I64, | ||
| 1492 | // .MEMORY_ADDR_LEB, | ||
| 1493 | // .MEMORY_ADDR_LEB64, | ||
| 1494 | // .MEMORY_ADDR_SLEB, | ||
| 1495 | // .MEMORY_ADDR_SLEB64, | ||
| 1496 | // => { | ||
| 1497 | // assert(symbol.tag == .data); | ||
| 1498 | // if (symbol.flags.undefined) return 0; | ||
| 1499 | // const va: i33 = symbol.virtual_address; | ||
| 1500 | // return @intCast(va + relocation.addend); | ||
| 1501 | // }, | ||
| 1502 | // .EVENT_INDEX_LEB => @panic("TODO: expose this as an error, events are unsupported"), | ||
| 1503 | // .SECTION_OFFSET_I32 => { | ||
| 1504 | // const target_atom_index = wasm.symbol_atom.get(target_loc).?; | ||
| 1505 | // const target_atom = wasm.getAtom(target_atom_index); | ||
| 1506 | // const rel_value: i33 = target_atom.offset; | ||
| 1507 | // return @intCast(rel_value + relocation.addend); | ||
| 1508 | // }, | ||
| 1509 | // .FUNCTION_OFFSET_I32 => { | ||
| 1510 | // if (symbol.flags.undefined) { | ||
| 1511 | // const val = atom.tombstone(wasm) orelse relocation.addend; | ||
| 1512 | // return @bitCast(val); | ||
| 1513 | // } | ||
| 1514 | // const target_atom_index = wasm.symbol_atom.get(target_loc).?; | ||
| 1515 | // const target_atom = wasm.getAtom(target_atom_index); | ||
| 1516 | // const rel_value: i33 = target_atom.offset; | ||
| 1517 | // return @intCast(rel_value + relocation.addend); | ||
| 1518 | // }, | ||
| 1519 | // .MEMORY_ADDR_TLS_SLEB, | ||
| 1520 | // .MEMORY_ADDR_TLS_SLEB64, | ||
| 1521 | // => { | ||
| 1522 | // const va: i33 = symbol.virtual_address; | ||
| 1523 | // return @intCast(va + relocation.addend); | ||
| 1524 | // }, | ||
| 1525 | // }; | ||
| 1526 | //} | ||
| 1527 | |||
| 1528 | ///// For a given `Atom` returns whether it has a tombstone value or not. | ||
| 1529 | ///// This defines whether we want a specific value when a section is dead. | ||
| 1530 | //fn tombstone(atom: Atom, wasm: *const Wasm) ?i64 { | ||
| 1531 | // const atom_name = wasm.finalSymbolByLoc(atom.symbolLoc()).name; | ||
| 1532 | // if (atom_name == wasm.custom_sections.@".debug_ranges".name or | ||
| 1533 | // atom_name == wasm.custom_sections.@".debug_loc".name) | ||
| 1534 | // { | ||
| 1535 | // return -2; | ||
| 1536 | // } else if (mem.startsWith(u8, atom_name.slice(wasm), ".debug_")) { | ||
| 1537 | // return -1; | ||
| 1538 | // } else { | ||
| 1539 | // return null; | ||
| 1540 | // } | ||
| 1541 | //} | ||
| 1542 | |||
| 1543 | fn uleb128size(x: u32) u32 { | 1401 | fn uleb128size(x: u32) u32 { |
| 1544 | var value = x; | 1402 | var value = x; |
| 1545 | var size: u32 = 0; | 1403 | var size: u32 = 0; |
src/link/Wasm/Object.zig+206-71| ... | @@ -36,12 +36,16 @@ global_imports: RelativeSlice, | ... | @@ -36,12 +36,16 @@ global_imports: RelativeSlice, |
| 36 | table_imports: RelativeSlice, | 36 | table_imports: RelativeSlice, |
| 37 | /// Points into Wasm object_custom_segments | 37 | /// Points into Wasm object_custom_segments |
| 38 | custom_segments: RelativeSlice, | 38 | custom_segments: RelativeSlice, |
| 39 | /// For calculating local section index from `Wasm.ObjectSectionIndex`. | ||
| 40 | local_section_index_base: u32, | ||
| 41 | /// Points into Wasm object_init_funcs | 39 | /// Points into Wasm object_init_funcs |
| 42 | init_funcs: RelativeSlice, | 40 | init_funcs: RelativeSlice, |
| 43 | /// Points into Wasm object_comdats | 41 | /// Points into Wasm object_comdats |
| 44 | comdats: RelativeSlice, | 42 | comdats: RelativeSlice, |
| 43 | /// Guaranteed to be non-null when functions has nonzero length. | ||
| 44 | code_section_index: ?Wasm.ObjectSectionIndex, | ||
| 45 | /// Guaranteed to be non-null when globals has nonzero length. | ||
| 46 | global_section_index: ?Wasm.ObjectSectionIndex, | ||
| 47 | /// Guaranteed to be non-null when data segments has nonzero length. | ||
| 48 | data_section_index: ?Wasm.ObjectSectionIndex, | ||
| 45 | 49 | ||
| 46 | pub const RelativeSlice = struct { | 50 | pub const RelativeSlice = struct { |
| 47 | off: u32, | 51 | off: u32, |
| ... | @@ -52,7 +56,8 @@ pub const SegmentInfo = struct { | ... | @@ -52,7 +56,8 @@ pub const SegmentInfo = struct { |
| 52 | name: Wasm.String, | 56 | name: Wasm.String, |
| 53 | flags: Flags, | 57 | flags: Flags, |
| 54 | 58 | ||
| 55 | const Flags = packed struct(u32) { | 59 | /// Matches the ABI. |
| 60 | pub const Flags = packed struct(u32) { | ||
| 56 | /// Signals that the segment contains only null terminated strings allowing | 61 | /// Signals that the segment contains only null terminated strings allowing |
| 57 | /// the linker to perform merging. | 62 | /// the linker to perform merging. |
| 58 | strings: bool, | 63 | strings: bool, |
| ... | @@ -101,6 +106,37 @@ pub const SubsectionType = enum(u8) { | ... | @@ -101,6 +106,37 @@ pub const SubsectionType = enum(u8) { |
| 101 | symbol_table = 8, | 106 | symbol_table = 8, |
| 102 | }; | 107 | }; |
| 103 | 108 | ||
| 109 | /// Specified by https://github.com/WebAssembly/tool-conventions/blob/main/Linking.md | ||
| 110 | pub const RelocationType = enum(u8) { | ||
| 111 | function_index_leb = 0, | ||
| 112 | table_index_sleb = 1, | ||
| 113 | table_index_i32 = 2, | ||
| 114 | memory_addr_leb = 3, | ||
| 115 | memory_addr_sleb = 4, | ||
| 116 | memory_addr_i32 = 5, | ||
| 117 | type_index_leb = 6, | ||
| 118 | global_index_leb = 7, | ||
| 119 | function_offset_i32 = 8, | ||
| 120 | section_offset_i32 = 9, | ||
| 121 | event_index_leb = 10, | ||
| 122 | memory_addr_rel_sleb = 11, | ||
| 123 | table_index_rel_sleb = 12, | ||
| 124 | global_index_i32 = 13, | ||
| 125 | memory_addr_leb64 = 14, | ||
| 126 | memory_addr_sleb64 = 15, | ||
| 127 | memory_addr_i64 = 16, | ||
| 128 | memory_addr_rel_sleb64 = 17, | ||
| 129 | table_index_sleb64 = 18, | ||
| 130 | table_index_i64 = 19, | ||
| 131 | table_number_leb = 20, | ||
| 132 | memory_addr_tls_sleb = 21, | ||
| 133 | function_offset_i64 = 22, | ||
| 134 | memory_addr_locrel_i32 = 23, | ||
| 135 | table_index_rel_sleb64 = 24, | ||
| 136 | memory_addr_tls_sleb64 = 25, | ||
| 137 | function_index_i32 = 26, | ||
| 138 | }; | ||
| 139 | |||
| 104 | pub const Symbol = struct { | 140 | pub const Symbol = struct { |
| 105 | flags: Wasm.SymbolFlags, | 141 | flags: Wasm.SymbolFlags, |
| 106 | name: Wasm.OptionalString, | 142 | name: Wasm.OptionalString, |
| ... | @@ -245,7 +281,8 @@ pub fn parse( | ... | @@ -245,7 +281,8 @@ pub fn parse( |
| 245 | const global_imports_start: u32 = @intCast(wasm.object_global_imports.entries.len); | 281 | const global_imports_start: u32 = @intCast(wasm.object_global_imports.entries.len); |
| 246 | const table_imports_start: u32 = @intCast(wasm.object_table_imports.entries.len); | 282 | const table_imports_start: u32 = @intCast(wasm.object_table_imports.entries.len); |
| 247 | const local_section_index_base = wasm.object_total_sections; | 283 | const local_section_index_base = wasm.object_total_sections; |
| 248 | const source_location: Wasm.SourceLocation = .fromObject(@enumFromInt(wasm.objects.items.len), wasm); | 284 | const object_index: Wasm.ObjectIndex = @enumFromInt(wasm.objects.items.len); |
| 285 | const source_location: Wasm.SourceLocation = .fromObject(object_index, wasm); | ||
| 249 | 286 | ||
| 250 | ss.clear(); | 287 | ss.clear(); |
| 251 | 288 | ||
| ... | @@ -254,6 +291,9 @@ pub fn parse( | ... | @@ -254,6 +291,9 @@ pub fn parse( |
| 254 | var saw_linking_section = false; | 291 | var saw_linking_section = false; |
| 255 | var has_tls = false; | 292 | var has_tls = false; |
| 256 | var table_import_symbol_count: usize = 0; | 293 | var table_import_symbol_count: usize = 0; |
| 294 | var code_section_index: ?Wasm.ObjectSectionIndex = null; | ||
| 295 | var global_section_index: ?Wasm.ObjectSectionIndex = null; | ||
| 296 | var data_section_index: ?Wasm.ObjectSectionIndex = null; | ||
| 257 | while (pos < bytes.len) : (wasm.object_total_sections += 1) { | 297 | while (pos < bytes.len) : (wasm.object_total_sections += 1) { |
| 258 | const section_index: Wasm.ObjectSectionIndex = @enumFromInt(wasm.object_total_sections); | 298 | const section_index: Wasm.ObjectSectionIndex = @enumFromInt(wasm.object_total_sections); |
| 259 | 299 | ||
| ... | @@ -365,7 +405,8 @@ pub fn parse( | ... | @@ -365,7 +405,8 @@ pub fn parse( |
| 365 | switch (tag) { | 405 | switch (tag) { |
| 366 | .data => { | 406 | .data => { |
| 367 | const name, pos = readBytes(bytes, pos); | 407 | const name, pos = readBytes(bytes, pos); |
| 368 | symbol.name = (try wasm.internString(name)).toOptional(); | 408 | const interned_name = try wasm.internString(name); |
| 409 | symbol.name = interned_name.toOptional(); | ||
| 369 | if (symbol.flags.undefined) { | 410 | if (symbol.flags.undefined) { |
| 370 | symbol.pointee = .data_import; | 411 | symbol.pointee = .data_import; |
| 371 | } else { | 412 | } else { |
| ... | @@ -376,7 +417,7 @@ pub fn parse( | ... | @@ -376,7 +417,7 @@ pub fn parse( |
| 376 | .segment = @enumFromInt(data_segment_start + segment_index), | 417 | .segment = @enumFromInt(data_segment_start + segment_index), |
| 377 | .offset = segment_offset, | 418 | .offset = segment_offset, |
| 378 | .size = size, | 419 | .size = size, |
| 379 | .name = symbol.name, | 420 | .name = interned_name, |
| 380 | .flags = symbol.flags, | 421 | .flags = symbol.flags, |
| 381 | }); | 422 | }); |
| 382 | symbol.pointee = .{ | 423 | symbol.pointee = .{ |
| ... | @@ -468,7 +509,7 @@ pub fn parse( | ... | @@ -468,7 +509,7 @@ pub fn parse( |
| 468 | var prev_offset: u32 = 0; | 509 | var prev_offset: u32 = 0; |
| 469 | try wasm.object_relocations.ensureUnusedCapacity(gpa, count); | 510 | try wasm.object_relocations.ensureUnusedCapacity(gpa, count); |
| 470 | for (0..count) |_| { | 511 | for (0..count) |_| { |
| 471 | const tag: Wasm.ObjectRelocation.Tag = @enumFromInt(bytes[pos]); | 512 | const tag: RelocationType = @enumFromInt(bytes[pos]); |
| 472 | pos += 1; | 513 | pos += 1; |
| 473 | const offset, pos = readLeb(u32, bytes, pos); | 514 | const offset, pos = readLeb(u32, bytes, pos); |
| 474 | const index, pos = readLeb(u32, bytes, pos); | 515 | const index, pos = readLeb(u32, bytes, pos); |
| ... | @@ -477,75 +518,134 @@ pub fn parse( | ... | @@ -477,75 +518,134 @@ pub fn parse( |
| 477 | return diags.failParse(path, "relocation entries not sorted by offset", .{}); | 518 | return diags.failParse(path, "relocation entries not sorted by offset", .{}); |
| 478 | prev_offset = offset; | 519 | prev_offset = offset; |
| 479 | 520 | ||
| 521 | const sym = &ss.symbol_table.items[index]; | ||
| 522 | |||
| 480 | switch (tag) { | 523 | switch (tag) { |
| 481 | .MEMORY_ADDR_LEB, | 524 | .memory_addr_leb, |
| 482 | .MEMORY_ADDR_SLEB, | 525 | .memory_addr_sleb, |
| 483 | .MEMORY_ADDR_I32, | 526 | .memory_addr_i32, |
| 484 | .MEMORY_ADDR_REL_SLEB, | 527 | .memory_addr_rel_sleb, |
| 485 | .MEMORY_ADDR_LEB64, | 528 | .memory_addr_leb64, |
| 486 | .MEMORY_ADDR_SLEB64, | 529 | .memory_addr_sleb64, |
| 487 | .MEMORY_ADDR_I64, | 530 | .memory_addr_i64, |
| 488 | .MEMORY_ADDR_REL_SLEB64, | 531 | .memory_addr_rel_sleb64, |
| 489 | .MEMORY_ADDR_TLS_SLEB, | 532 | .memory_addr_tls_sleb, |
| 490 | .MEMORY_ADDR_LOCREL_I32, | 533 | .memory_addr_locrel_i32, |
| 491 | .MEMORY_ADDR_TLS_SLEB64, | 534 | .memory_addr_tls_sleb64, |
| 492 | => { | 535 | => { |
| 493 | const addend: i32, pos = readLeb(i32, bytes, pos); | 536 | const addend: i32, pos = readLeb(i32, bytes, pos); |
| 494 | wasm.object_relocations.appendAssumeCapacity(.{ | 537 | wasm.object_relocations.appendAssumeCapacity(switch (sym.pointee) { |
| 495 | .tag = tag, | 538 | .data => |data| .{ |
| 496 | .offset = offset, | 539 | .tag = .fromType(tag), |
| 497 | .pointee = .{ .data = ss.symbol_table.items[index].pointee.data }, | 540 | .offset = offset, |
| 498 | .addend = addend, | 541 | .pointee = .{ .data = data }, |
| 542 | .addend = addend, | ||
| 543 | }, | ||
| 544 | .data_import => .{ | ||
| 545 | .tag = .fromTypeImport(tag), | ||
| 546 | .offset = offset, | ||
| 547 | .pointee = .{ .symbol_name = sym.name.unwrap().? }, | ||
| 548 | .addend = addend, | ||
| 549 | }, | ||
| 550 | else => unreachable, | ||
| 499 | }); | 551 | }); |
| 500 | }, | 552 | }, |
| 501 | .FUNCTION_OFFSET_I32, | 553 | .function_offset_i32, .function_offset_i64 => { |
| 502 | .FUNCTION_OFFSET_I64, | ||
| 503 | => { | ||
| 504 | const addend: i32, pos = readLeb(i32, bytes, pos); | 554 | const addend: i32, pos = readLeb(i32, bytes, pos); |
| 505 | wasm.object_relocations.appendAssumeCapacity(.{ | 555 | wasm.object_relocations.appendAssumeCapacity(switch (sym.pointee) { |
| 506 | .tag = tag, | 556 | .function => .{ |
| 507 | .offset = offset, | 557 | .tag = .fromType(tag), |
| 508 | .pointee = .{ .function = ss.symbol_table.items[index].pointee.function }, | 558 | .offset = offset, |
| 509 | .addend = addend, | 559 | .pointee = .{ .function = sym.pointee.function }, |
| 560 | .addend = addend, | ||
| 561 | }, | ||
| 562 | .function_import => .{ | ||
| 563 | .tag = .fromTypeImport(tag), | ||
| 564 | .offset = offset, | ||
| 565 | .pointee = .{ .symbol_name = sym.name.unwrap().? }, | ||
| 566 | .addend = addend, | ||
| 567 | }, | ||
| 568 | else => unreachable, | ||
| 510 | }); | 569 | }); |
| 511 | }, | 570 | }, |
| 512 | .SECTION_OFFSET_I32 => { | 571 | .section_offset_i32 => { |
| 513 | const addend: i32, pos = readLeb(i32, bytes, pos); | 572 | const addend: i32, pos = readLeb(i32, bytes, pos); |
| 514 | wasm.object_relocations.appendAssumeCapacity(.{ | 573 | wasm.object_relocations.appendAssumeCapacity(.{ |
| 515 | .tag = tag, | 574 | .tag = .section_offset_i32, |
| 516 | .offset = offset, | 575 | .offset = offset, |
| 517 | .pointee = .{ .section = ss.symbol_table.items[index].pointee.section }, | 576 | .pointee = .{ .section = sym.pointee.section }, |
| 518 | .addend = addend, | 577 | .addend = addend, |
| 519 | }); | 578 | }); |
| 520 | }, | 579 | }, |
| 521 | .TYPE_INDEX_LEB => { | 580 | .type_index_leb => { |
| 522 | wasm.object_relocations.appendAssumeCapacity(.{ | 581 | wasm.object_relocations.appendAssumeCapacity(.{ |
| 523 | .tag = tag, | 582 | .tag = .type_index_leb, |
| 524 | .offset = offset, | 583 | .offset = offset, |
| 525 | .pointee = .{ .type_index = ss.func_types.items[index] }, | 584 | .pointee = .{ .type_index = ss.func_types.items[index] }, |
| 526 | .addend = undefined, | 585 | .addend = undefined, |
| 527 | }); | 586 | }); |
| 528 | }, | 587 | }, |
| 529 | .FUNCTION_INDEX_LEB, | 588 | .function_index_leb, |
| 530 | .FUNCTION_INDEX_I32, | 589 | .function_index_i32, |
| 531 | .GLOBAL_INDEX_LEB, | 590 | .table_index_sleb, |
| 532 | .GLOBAL_INDEX_I32, | 591 | .table_index_i32, |
| 533 | .TABLE_INDEX_SLEB, | 592 | .table_index_sleb64, |
| 534 | .TABLE_INDEX_I32, | 593 | .table_index_i64, |
| 535 | .TABLE_INDEX_SLEB64, | 594 | .table_index_rel_sleb, |
| 536 | .TABLE_INDEX_I64, | 595 | .table_index_rel_sleb64, |
| 537 | .TABLE_NUMBER_LEB, | ||
| 538 | .TABLE_INDEX_REL_SLEB, | ||
| 539 | .TABLE_INDEX_REL_SLEB64, | ||
| 540 | .TAG_INDEX_LEB, | ||
| 541 | => { | 596 | => { |
| 542 | wasm.object_relocations.appendAssumeCapacity(.{ | 597 | wasm.object_relocations.appendAssumeCapacity(switch (sym.pointee) { |
| 543 | .tag = tag, | 598 | .function => .{ |
| 544 | .offset = offset, | 599 | .tag = .fromType(tag), |
| 545 | .pointee = .{ .symbol_name = ss.symbol_table.items[index].name.unwrap().? }, | 600 | .offset = offset, |
| 546 | .addend = undefined, | 601 | .pointee = .{ .function = sym.pointee.function }, |
| 602 | .addend = undefined, | ||
| 603 | }, | ||
| 604 | .function_import => .{ | ||
| 605 | .tag = .fromTypeImport(tag), | ||
| 606 | .offset = offset, | ||
| 607 | .pointee = .{ .symbol_name = sym.name.unwrap().? }, | ||
| 608 | .addend = undefined, | ||
| 609 | }, | ||
| 610 | else => unreachable, | ||
| 611 | }); | ||
| 612 | }, | ||
| 613 | .global_index_leb, .global_index_i32 => { | ||
| 614 | wasm.object_relocations.appendAssumeCapacity(switch (sym.pointee) { | ||
| 615 | .global => .{ | ||
| 616 | .tag = .fromType(tag), | ||
| 617 | .offset = offset, | ||
| 618 | .pointee = .{ .global = sym.pointee.global }, | ||
| 619 | .addend = undefined, | ||
| 620 | }, | ||
| 621 | .global_import => .{ | ||
| 622 | .tag = .fromTypeImport(tag), | ||
| 623 | .offset = offset, | ||
| 624 | .pointee = .{ .symbol_name = sym.name.unwrap().? }, | ||
| 625 | .addend = undefined, | ||
| 626 | }, | ||
| 627 | else => unreachable, | ||
| 628 | }); | ||
| 629 | }, | ||
| 630 | |||
| 631 | .table_number_leb => { | ||
| 632 | wasm.object_relocations.appendAssumeCapacity(switch (sym.pointee) { | ||
| 633 | .table => .{ | ||
| 634 | .tag = .fromType(tag), | ||
| 635 | .offset = offset, | ||
| 636 | .pointee = .{ .table = sym.pointee.table }, | ||
| 637 | .addend = undefined, | ||
| 638 | }, | ||
| 639 | .table_import => .{ | ||
| 640 | .tag = .fromTypeImport(tag), | ||
| 641 | .offset = offset, | ||
| 642 | .pointee = .{ .symbol_name = sym.name.unwrap().? }, | ||
| 643 | .addend = undefined, | ||
| 644 | }, | ||
| 645 | else => unreachable, | ||
| 547 | }); | 646 | }); |
| 548 | }, | 647 | }, |
| 648 | .event_index_leb => return diags.failParse(path, "unsupported relocation: R_WASM_EVENT_INDEX_LEB", .{}), | ||
| 549 | } | 649 | } |
| 550 | } | 650 | } |
| 551 | 651 | ||
| ... | @@ -684,11 +784,17 @@ pub fn parse( | ... | @@ -684,11 +784,17 @@ pub fn parse( |
| 684 | } | 784 | } |
| 685 | }, | 785 | }, |
| 686 | .global => { | 786 | .global => { |
| 787 | if (global_section_index != null) | ||
| 788 | return diags.failParse(path, "object has more than one global section", .{}); | ||
| 789 | global_section_index = section_index; | ||
| 790 | |||
| 791 | const section_start = pos; | ||
| 687 | const globals_len, pos = readLeb(u32, bytes, pos); | 792 | const globals_len, pos = readLeb(u32, bytes, pos); |
| 688 | for (try wasm.object_globals.addManyAsSlice(gpa, globals_len)) |*global| { | 793 | for (try wasm.object_globals.addManyAsSlice(gpa, globals_len)) |*global| { |
| 689 | const valtype, pos = readEnum(std.wasm.Valtype, bytes, pos); | 794 | const valtype, pos = readEnum(std.wasm.Valtype, bytes, pos); |
| 690 | const mutable = bytes[pos] == 0x01; | 795 | const mutable = bytes[pos] == 0x01; |
| 691 | pos += 1; | 796 | pos += 1; |
| 797 | const init_start = pos; | ||
| 692 | const expr, pos = try readInit(wasm, bytes, pos); | 798 | const expr, pos = try readInit(wasm, bytes, pos); |
| 693 | global.* = .{ | 799 | global.* = .{ |
| 694 | .name = .none, | 800 | .name = .none, |
| ... | @@ -699,6 +805,9 @@ pub fn parse( | ... | @@ -699,6 +805,9 @@ pub fn parse( |
| 699 | }, | 805 | }, |
| 700 | }, | 806 | }, |
| 701 | .expr = expr, | 807 | .expr = expr, |
| 808 | .object_index = object_index, | ||
| 809 | .offset = @intCast(init_start - section_start), | ||
| 810 | .size = @intCast(pos - init_start), | ||
| 702 | }; | 811 | }; |
| 703 | } | 812 | } |
| 704 | }, | 813 | }, |
| ... | @@ -728,10 +837,14 @@ pub fn parse( | ... | @@ -728,10 +837,14 @@ pub fn parse( |
| 728 | start_function = @enumFromInt(functions_start + index); | 837 | start_function = @enumFromInt(functions_start + index); |
| 729 | }, | 838 | }, |
| 730 | .element => { | 839 | .element => { |
| 731 | log.warn("unimplemented: element section in {}", .{path}); | 840 | log.warn("unimplemented: element section in {} {s}", .{ path, archive_member_name.? }); |
| 732 | pos = section_end; | 841 | pos = section_end; |
| 733 | }, | 842 | }, |
| 734 | .code => { | 843 | .code => { |
| 844 | if (code_section_index != null) | ||
| 845 | return diags.failParse(path, "object has more than one code section", .{}); | ||
| 846 | code_section_index = section_index; | ||
| 847 | |||
| 735 | const start = pos; | 848 | const start = pos; |
| 736 | const count, pos = readLeb(u32, bytes, pos); | 849 | const count, pos = readLeb(u32, bytes, pos); |
| 737 | for (try wasm.object_functions.addManyAsSlice(gpa, count)) |*elem| { | 850 | for (try wasm.object_functions.addManyAsSlice(gpa, count)) |*elem| { |
| ... | @@ -745,12 +858,16 @@ pub fn parse( | ... | @@ -745,12 +858,16 @@ pub fn parse( |
| 745 | .type_index = undefined, // populated from func_types | 858 | .type_index = undefined, // populated from func_types |
| 746 | .code = payload, | 859 | .code = payload, |
| 747 | .offset = offset, | 860 | .offset = offset, |
| 748 | .section_index = section_index, | 861 | .object_index = object_index, |
| 749 | .source_location = source_location, | ||
| 750 | }; | 862 | }; |
| 751 | } | 863 | } |
| 752 | }, | 864 | }, |
| 753 | .data => { | 865 | .data => { |
| 866 | if (data_section_index != null) | ||
| 867 | return diags.failParse(path, "object has more than one data section", .{}); | ||
| 868 | data_section_index = section_index; | ||
| 869 | |||
| 870 | const section_start = pos; | ||
| 754 | const count, pos = readLeb(u32, bytes, pos); | 871 | const count, pos = readLeb(u32, bytes, pos); |
| 755 | for (try wasm.object_data_segments.addManyAsSlice(gpa, count)) |*elem| { | 872 | for (try wasm.object_data_segments.addManyAsSlice(gpa, count)) |*elem| { |
| 756 | const flags, pos = readEnum(DataSegmentFlags, bytes, pos); | 873 | const flags, pos = readEnum(DataSegmentFlags, bytes, pos); |
| ... | @@ -761,12 +878,17 @@ pub fn parse( | ... | @@ -761,12 +878,17 @@ pub fn parse( |
| 761 | //const expr, pos = if (flags != .passive) try readInit(wasm, bytes, pos) else .{ .none, pos }; | 878 | //const expr, pos = if (flags != .passive) try readInit(wasm, bytes, pos) else .{ .none, pos }; |
| 762 | if (flags != .passive) pos = try skipInit(bytes, pos); | 879 | if (flags != .passive) pos = try skipInit(bytes, pos); |
| 763 | const data_len, pos = readLeb(u32, bytes, pos); | 880 | const data_len, pos = readLeb(u32, bytes, pos); |
| 881 | const segment_start = pos; | ||
| 764 | const payload = try wasm.addRelocatableDataPayload(bytes[pos..][0..data_len]); | 882 | const payload = try wasm.addRelocatableDataPayload(bytes[pos..][0..data_len]); |
| 765 | pos += data_len; | 883 | pos += data_len; |
| 766 | elem.* = .{ | 884 | elem.* = .{ |
| 767 | .payload = payload, | 885 | .payload = payload, |
| 768 | .name = .none, // Populated from symbol table | 886 | .name = .none, // Populated from segment_info |
| 769 | .flags = .{}, // Populated from symbol table and segment_info | 887 | .flags = .{ |
| 888 | .is_passive = flags == .passive, | ||
| 889 | }, // Remainder populated from segment_info | ||
| 890 | .offset = @intCast(segment_start - section_start), | ||
| 891 | .object_index = object_index, | ||
| 770 | }; | 892 | }; |
| 771 | } | 893 | } |
| 772 | }, | 894 | }, |
| ... | @@ -1033,8 +1155,10 @@ pub fn parse( | ... | @@ -1033,8 +1155,10 @@ pub fn parse( |
| 1033 | } | 1155 | } |
| 1034 | }, | 1156 | }, |
| 1035 | .data_import => { | 1157 | .data_import => { |
| 1036 | const name = symbol.name.unwrap().?; | 1158 | if (symbol.flags.undefined and symbol.flags.binding == .local) { |
| 1037 | log.warn("TODO data import '{s}'", .{name.slice(wasm)}); | 1159 | const name = symbol.name.slice(wasm).?; |
| 1160 | diags.addParseError(path, "local symbol '{s}' references import", .{name}); | ||
| 1161 | } | ||
| 1038 | }, | 1162 | }, |
| 1039 | .data => continue, // `wasm.object_datas` has already been populated. | 1163 | .data => continue, // `wasm.object_datas` has already been populated. |
| 1040 | }; | 1164 | }; |
| ... | @@ -1055,16 +1179,21 @@ pub fn parse( | ... | @@ -1055,16 +1179,21 @@ pub fn parse( |
| 1055 | } | 1179 | } |
| 1056 | 1180 | ||
| 1057 | // Apply segment_info. | 1181 | // Apply segment_info. |
| 1058 | for (wasm.object_data_segments.items[data_segment_start..], ss.segment_info.items) |*data, info| { | 1182 | const data_segments = wasm.object_data_segments.items[data_segment_start..]; |
| 1183 | if (data_segments.len != ss.segment_info.items.len) { | ||
| 1184 | return diags.failParse(path, "expected {d} segment_info entries; found {d}", .{ | ||
| 1185 | data_segments.len, ss.segment_info.items.len, | ||
| 1186 | }); | ||
| 1187 | } | ||
| 1188 | for (data_segments, ss.segment_info.items) |*data, info| { | ||
| 1059 | data.name = info.name.toOptional(); | 1189 | data.name = info.name.toOptional(); |
| 1060 | data.flags.strings = info.flags.strings; | 1190 | data.flags = .{ |
| 1061 | data.flags.tls = data.flags.tls or info.flags.tls; | 1191 | .is_passive = data.flags.is_passive, |
| 1062 | data.flags.no_strip = info.flags.retain; | 1192 | .strings = info.flags.strings, |
| 1063 | data.flags.alignment = info.flags.alignment; | 1193 | .tls = info.flags.tls, |
| 1064 | if (data.flags.undefined and data.flags.binding == .local) { | 1194 | .retain = info.flags.retain, |
| 1065 | const name = info.name.slice(wasm); | 1195 | .alignment = info.flags.alignment, |
| 1066 | diags.addParseError(path, "local symbol '{s}' references import", .{name}); | 1196 | }; |
| 1067 | } | ||
| 1068 | } | 1197 | } |
| 1069 | 1198 | ||
| 1070 | // Check for indirect function table in case of an MVP object file. | 1199 | // Check for indirect function table in case of an MVP object file. |
| ... | @@ -1106,6 +1235,10 @@ pub fn parse( | ... | @@ -1106,6 +1235,10 @@ pub fn parse( |
| 1106 | }); | 1235 | }); |
| 1107 | } | 1236 | } |
| 1108 | 1237 | ||
| 1238 | const functions_len: u32 = @intCast(wasm.object_functions.items.len - functions_start); | ||
| 1239 | if (functions_len > 0 and code_section_index == null) | ||
| 1240 | return diags.failParse(path, "code section missing ({d} functions)", .{functions_len}); | ||
| 1241 | |||
| 1109 | return .{ | 1242 | return .{ |
| 1110 | .version = version, | 1243 | .version = version, |
| 1111 | .path = path, | 1244 | .path = path, |
| ... | @@ -1114,7 +1247,7 @@ pub fn parse( | ... | @@ -1114,7 +1247,7 @@ pub fn parse( |
| 1114 | .features = features, | 1247 | .features = features, |
| 1115 | .functions = .{ | 1248 | .functions = .{ |
| 1116 | .off = functions_start, | 1249 | .off = functions_start, |
| 1117 | .len = @intCast(wasm.object_functions.items.len - functions_start), | 1250 | .len = functions_len, |
| 1118 | }, | 1251 | }, |
| 1119 | .function_imports = .{ | 1252 | .function_imports = .{ |
| 1120 | .off = function_imports_start, | 1253 | .off = function_imports_start, |
| ... | @@ -1140,7 +1273,9 @@ pub fn parse( | ... | @@ -1140,7 +1273,9 @@ pub fn parse( |
| 1140 | .off = custom_segment_start, | 1273 | .off = custom_segment_start, |
| 1141 | .len = @intCast(wasm.object_custom_segments.entries.len - custom_segment_start), | 1274 | .len = @intCast(wasm.object_custom_segments.entries.len - custom_segment_start), |
| 1142 | }, | 1275 | }, |
| 1143 | .local_section_index_base = local_section_index_base, | 1276 | .code_section_index = code_section_index, |
| 1277 | .global_section_index = global_section_index, | ||
| 1278 | .data_section_index = data_section_index, | ||
| 1144 | }; | 1279 | }; |
| 1145 | } | 1280 | } |
| 1146 | 1281 |