| author | |
| committer | |
| log | 728103467edba5f3407b1aaa89c9b6dda9432884 |
| tree | ef64a910bd3240e28496e49a7ee98bb784c8edd8 |
| parent | fbbb54bab212e8db251ea7409945d5cecfd732c6 |
5 files changed, 129 insertions(+), 92 deletions(-)
src/arch/wasm/CodeGen.zig+27-3| ... | @@ -1021,7 +1021,20 @@ fn emitWValue(cg: *CodeGen, value: WValue) InnerError!void { | ... | @@ -1021,7 +1021,20 @@ fn emitWValue(cg: *CodeGen, value: WValue) InnerError!void { |
| 1021 | .float32 => |val| try cg.addInst(.{ .tag = .f32_const, .data = .{ .float32 = val } }), | 1021 | .float32 => |val| try cg.addInst(.{ .tag = .f32_const, .data = .{ .float32 = val } }), |
| 1022 | .float64 => |val| try cg.addFloat64(val), | 1022 | .float64 => |val| try cg.addFloat64(val), |
| 1023 | .nav_ref => |nav_ref| { | 1023 | .nav_ref => |nav_ref| { |
| 1024 | if (nav_ref.offset == 0) { | 1024 | const wasm = cg.wasm; |
| 1025 | const comp = wasm.base.comp; | ||
| 1026 | const zcu = comp.zcu.?; | ||
| 1027 | const ip = &zcu.intern_pool; | ||
| 1028 | const ip_index = ip.getNav(nav_ref.nav_index).status.resolved.val; | ||
| 1029 | if (ip.isFunctionType(ip.typeOf(ip_index))) { | ||
| 1030 | assert(nav_ref.offset == 0); | ||
| 1031 | const gop = try wasm.indirect_function_table.getOrPut(comp.gpa, ip_index); | ||
| 1032 | if (!gop.found_existing) gop.value_ptr.* = {}; | ||
| 1033 | try cg.addInst(.{ | ||
| 1034 | .tag = .func_ref, | ||
| 1035 | .data = .{ .indirect_function_table_index = @enumFromInt(gop.index) }, | ||
| 1036 | }); | ||
| 1037 | } else if (nav_ref.offset == 0) { | ||
| 1025 | try cg.addInst(.{ .tag = .nav_ref, .data = .{ .nav_index = nav_ref.nav_index } }); | 1038 | try cg.addInst(.{ .tag = .nav_ref, .data = .{ .nav_index = nav_ref.nav_index } }); |
| 1026 | } else { | 1039 | } else { |
| 1027 | try cg.addInst(.{ | 1040 | try cg.addInst(.{ |
| ... | @@ -1037,8 +1050,19 @@ fn emitWValue(cg: *CodeGen, value: WValue) InnerError!void { | ... | @@ -1037,8 +1050,19 @@ fn emitWValue(cg: *CodeGen, value: WValue) InnerError!void { |
| 1037 | }, | 1050 | }, |
| 1038 | .uav_ref => |uav| { | 1051 | .uav_ref => |uav| { |
| 1039 | const wasm = cg.wasm; | 1052 | const wasm = cg.wasm; |
| 1040 | const is_obj = wasm.base.comp.config.output_mode == .Obj; | 1053 | const comp = wasm.base.comp; |
| 1041 | if (uav.offset == 0) { | 1054 | const is_obj = comp.config.output_mode == .Obj; |
| 1055 | const zcu = comp.zcu.?; | ||
| 1056 | const ip = &zcu.intern_pool; | ||
| 1057 | if (ip.isFunctionType(ip.typeOf(uav.ip_index))) { | ||
| 1058 | assert(uav.offset == 0); | ||
| 1059 | const gop = try wasm.indirect_function_table.getOrPut(comp.gpa, uav.ip_index); | ||
| 1060 | if (!gop.found_existing) gop.value_ptr.* = {}; | ||
| 1061 | try cg.addInst(.{ | ||
| 1062 | .tag = .func_ref, | ||
| 1063 | .data = .{ .indirect_function_table_index = @enumFromInt(gop.index) }, | ||
| 1064 | }); | ||
| 1065 | } else if (uav.offset == 0) { | ||
| 1042 | try cg.addInst(.{ | 1066 | try cg.addInst(.{ |
| 1043 | .tag = .uav_ref, | 1067 | .tag = .uav_ref, |
| 1044 | .data = if (is_obj) .{ | 1068 | .data = if (is_obj) .{ |
src/arch/wasm/Emit.zig+23-31| ... | @@ -76,7 +76,16 @@ pub fn lowerToCode(emit: *Emit) Error!void { | ... | @@ -76,7 +76,16 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 76 | inst += 1; | 76 | inst += 1; |
| 77 | continue :loop tags[inst]; | 77 | continue :loop tags[inst]; |
| 78 | }, | 78 | }, |
| 79 | 79 | .func_ref => { | |
| 80 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i32_const)); | ||
| 81 | if (is_obj) { | ||
| 82 | @panic("TODO"); | ||
| 83 | } else { | ||
| 84 | leb.writeUleb128(code.fixedWriter(), @intFromEnum(datas[inst].indirect_function_table_index)) catch unreachable; | ||
| 85 | } | ||
| 86 | inst += 1; | ||
| 87 | continue :loop tags[inst]; | ||
| 88 | }, | ||
| 80 | .dbg_line => { | 89 | .dbg_line => { |
| 81 | inst += 1; | 90 | inst += 1; |
| 82 | continue :loop tags[inst]; | 91 | continue :loop tags[inst]; |
| ... | @@ -938,40 +947,23 @@ fn navRefOff(wasm: *Wasm, code: *std.ArrayListUnmanaged(u8), data: Mir.NavRefOff | ... | @@ -938,40 +947,23 @@ fn navRefOff(wasm: *Wasm, code: *std.ArrayListUnmanaged(u8), data: Mir.NavRefOff |
| 938 | const gpa = comp.gpa; | 947 | const gpa = comp.gpa; |
| 939 | const is_obj = comp.config.output_mode == .Obj; | 948 | const is_obj = comp.config.output_mode == .Obj; |
| 940 | const nav_ty = ip.getNav(data.nav_index).typeOf(ip); | 949 | const nav_ty = ip.getNav(data.nav_index).typeOf(ip); |
| 950 | assert(!ip.isFunctionType(nav_ty)); | ||
| 941 | 951 | ||
| 942 | try code.ensureUnusedCapacity(gpa, 11); | 952 | try code.ensureUnusedCapacity(gpa, 11); |
| 943 | 953 | ||
| 944 | if (ip.isFunctionType(nav_ty)) { | 954 | const opcode: std.wasm.Opcode = if (is_wasm32) .i32_const else .i64_const; |
| 945 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i32_const)); | 955 | code.appendAssumeCapacity(@intFromEnum(opcode)); |
| 946 | assert(data.offset == 0); | 956 | if (is_obj) { |
| 947 | if (is_obj) { | 957 | try wasm.out_relocs.append(gpa, .{ |
| 948 | try wasm.out_relocs.append(gpa, .{ | 958 | .offset = @intCast(code.items.len), |
| 949 | .offset = @intCast(code.items.len), | 959 | .pointee = .{ .symbol_index = try wasm.navSymbolIndex(data.nav_index) }, |
| 950 | .pointee = .{ .symbol_index = try wasm.navSymbolIndex(data.nav_index) }, | 960 | .tag = if (is_wasm32) .MEMORY_ADDR_LEB else .MEMORY_ADDR_LEB64, |
| 951 | .tag = .TABLE_INDEX_SLEB, | 961 | .addend = data.offset, |
| 952 | .addend = data.offset, | 962 | }); |
| 953 | }); | 963 | code.appendNTimesAssumeCapacity(0, if (is_wasm32) 5 else 10); |
| 954 | code.appendNTimesAssumeCapacity(0, 5); | ||
| 955 | } else { | ||
| 956 | const function_imports_len: u32 = @intCast(wasm.function_imports.entries.len); | ||
| 957 | const func_index = Wasm.FunctionIndex.fromIpNav(wasm, data.nav_index).?; | ||
| 958 | leb.writeUleb128(code.fixedWriter(), function_imports_len + @intFromEnum(func_index)) catch unreachable; | ||
| 959 | } | ||
| 960 | } else { | 964 | } else { |
| 961 | const opcode: std.wasm.Opcode = if (is_wasm32) .i32_const else .i64_const; | 965 | const addr = wasm.navAddr(data.nav_index); |
| 962 | code.appendAssumeCapacity(@intFromEnum(opcode)); | 966 | leb.writeUleb128(code.fixedWriter(), @as(u32, @intCast(@as(i64, addr) + data.offset))) catch unreachable; |
| 963 | if (is_obj) { | ||
| 964 | try wasm.out_relocs.append(gpa, .{ | ||
| 965 | .offset = @intCast(code.items.len), | ||
| 966 | .pointee = .{ .symbol_index = try wasm.navSymbolIndex(data.nav_index) }, | ||
| 967 | .tag = if (is_wasm32) .MEMORY_ADDR_LEB else .MEMORY_ADDR_LEB64, | ||
| 968 | .addend = data.offset, | ||
| 969 | }); | ||
| 970 | code.appendNTimesAssumeCapacity(0, if (is_wasm32) 5 else 10); | ||
| 971 | } else { | ||
| 972 | const addr = wasm.navAddr(data.nav_index); | ||
| 973 | leb.writeUleb128(code.fixedWriter(), @as(u32, @intCast(@as(i64, addr) + data.offset))) catch unreachable; | ||
| 974 | } | ||
| 975 | } | 967 | } |
| 976 | } | 968 | } |
| 977 | 969 |
src/arch/wasm/Mir.zig+14-10| ... | @@ -65,9 +65,7 @@ pub const Inst = struct { | ... | @@ -65,9 +65,7 @@ pub const Inst = struct { |
| 65 | /// Lowers to an i32_const (wasm32) or i64_const (wasm64) which is the | 65 | /// Lowers to an i32_const (wasm32) or i64_const (wasm64) which is the |
| 66 | /// memory address of a named constant. | 66 | /// memory address of a named constant. |
| 67 | /// | 67 | /// |
| 68 | /// When this refers to a function, this always lowers to an i32_const | 68 | /// May not refer to a function. |
| 69 | /// which is the function index. When emitting an object file, this | ||
| 70 | /// adds a `Wasm.Relocation.Tag.TABLE_INDEX_SLEB` relocation. | ||
| 71 | /// | 69 | /// |
| 72 | /// Uses `nav_index`. | 70 | /// Uses `nav_index`. |
| 73 | nav_ref, | 71 | nav_ref, |
| ... | @@ -75,10 +73,15 @@ pub const Inst = struct { | ... | @@ -75,10 +73,15 @@ pub const Inst = struct { |
| 75 | /// memory address of named constant, offset by an integer value. | 73 | /// memory address of named constant, offset by an integer value. |
| 76 | /// When emitting an object file, this adds a relocation. | 74 | /// When emitting an object file, this adds a relocation. |
| 77 | /// | 75 | /// |
| 78 | /// This may not refer to a function. | 76 | /// May not refer to a function. |
| 79 | /// | 77 | /// |
| 80 | /// Uses `payload` pointing to a `NavRefOff`. | 78 | /// Uses `payload` pointing to a `NavRefOff`. |
| 81 | nav_ref_off, | 79 | nav_ref_off, |
| 80 | /// Lowers to an i32_const which is the index of the function in the | ||
| 81 | /// table section. | ||
| 82 | /// | ||
| 83 | /// Uses `indirect_function_table_index`. | ||
| 84 | func_ref, | ||
| 82 | /// Inserts debug information about the current line and column | 85 | /// Inserts debug information about the current line and column |
| 83 | /// of the source code | 86 | /// of the source code |
| 84 | /// | 87 | /// |
| ... | @@ -88,12 +91,6 @@ pub const Inst = struct { | ... | @@ -88,12 +91,6 @@ pub const Inst = struct { |
| 88 | /// names. | 91 | /// names. |
| 89 | /// Uses `tag`. | 92 | /// Uses `tag`. |
| 90 | errors_len, | 93 | errors_len, |
| 91 | /// Lowers to an i32_const (wasm32) or i64_const (wasm64) containing | ||
| 92 | /// the base address of the table of error code names, with each | ||
| 93 | /// element being a null-terminated slice. | ||
| 94 | /// | ||
| 95 | /// Uses `tag`. | ||
| 96 | error_name_table_ref, | ||
| 97 | /// Represents the end of a function body or an initialization expression | 94 | /// Represents the end of a function body or an initialization expression |
| 98 | /// | 95 | /// |
| 99 | /// Uses `tag` (no additional data). | 96 | /// Uses `tag` (no additional data). |
| ... | @@ -115,6 +112,12 @@ pub const Inst = struct { | ... | @@ -115,6 +112,12 @@ pub const Inst = struct { |
| 115 | /// | 112 | /// |
| 116 | /// Uses `tag`. | 113 | /// Uses `tag`. |
| 117 | @"return" = 0x0F, | 114 | @"return" = 0x0F, |
| 115 | /// Lowers to an i32_const (wasm32) or i64_const (wasm64) containing | ||
| 116 | /// the base address of the table of error code names, with each | ||
| 117 | /// element being a null-terminated slice. | ||
| 118 | /// | ||
| 119 | /// Uses `tag`. | ||
| 120 | error_name_table_ref, | ||
| 118 | /// Calls a function using `nav_index`. | 121 | /// Calls a function using `nav_index`. |
| 119 | call_nav, | 122 | call_nav, |
| 120 | /// Calls a function pointer by its function signature | 123 | /// Calls a function pointer by its function signature |
| ... | @@ -612,6 +615,7 @@ pub const Inst = struct { | ... | @@ -612,6 +615,7 @@ pub const Inst = struct { |
| 612 | intrinsic: Intrinsic, | 615 | intrinsic: Intrinsic, |
| 613 | uav_obj: Wasm.UavsObjIndex, | 616 | uav_obj: Wasm.UavsObjIndex, |
| 614 | uav_exe: Wasm.UavsExeIndex, | 617 | uav_exe: Wasm.UavsExeIndex, |
| 618 | indirect_function_table_index: Wasm.IndirectFunctionTableIndex, | ||
| 615 | 619 | ||
| 616 | comptime { | 620 | comptime { |
| 617 | switch (builtin.mode) { | 621 | switch (builtin.mode) { |
src/link/Wasm.zig+36-14| ... | @@ -235,6 +235,10 @@ global_imports: std.AutoArrayHashMapUnmanaged(String, GlobalImportId) = .empty, | ... | @@ -235,6 +235,10 @@ global_imports: std.AutoArrayHashMapUnmanaged(String, GlobalImportId) = .empty, |
| 235 | tables: std.AutoArrayHashMapUnmanaged(TableImport.Resolution, void) = .empty, | 235 | tables: std.AutoArrayHashMapUnmanaged(TableImport.Resolution, void) = .empty, |
| 236 | table_imports: std.AutoArrayHashMapUnmanaged(String, TableImport.Index) = .empty, | 236 | table_imports: std.AutoArrayHashMapUnmanaged(String, TableImport.Index) = .empty, |
| 237 | 237 | ||
| 238 | /// All functions that have had their address taken and therefore might be | ||
| 239 | /// called via a `call_indirect` function. | ||
| 240 | indirect_function_table: std.AutoArrayHashMapUnmanaged(InternPool.Index, void) = .empty, | ||
| 241 | |||
| 238 | error_name_table_ref_count: u32 = 0, | 242 | error_name_table_ref_count: u32 = 0, |
| 239 | 243 | ||
| 240 | /// Set to true if any `GLOBAL_INDEX` relocation is encountered with | 244 | /// Set to true if any `GLOBAL_INDEX` relocation is encountered with |
| ... | @@ -260,6 +264,11 @@ error_name_bytes: std.ArrayListUnmanaged(u8) = .empty, | ... | @@ -260,6 +264,11 @@ error_name_bytes: std.ArrayListUnmanaged(u8) = .empty, |
| 260 | /// is stored. No need to serialize; trivially reconstructed. | 264 | /// is stored. No need to serialize; trivially reconstructed. |
| 261 | error_name_offs: std.ArrayListUnmanaged(u32) = .empty, | 265 | error_name_offs: std.ArrayListUnmanaged(u32) = .empty, |
| 262 | 266 | ||
| 267 | /// Index into `Wasm.indirect_function_table`. | ||
| 268 | pub const IndirectFunctionTableIndex = enum(u32) { | ||
| 269 | _, | ||
| 270 | }; | ||
| 271 | |||
| 263 | pub const UavFixup = extern struct { | 272 | pub const UavFixup = extern struct { |
| 264 | uavs_exe_index: UavsExeIndex, | 273 | uavs_exe_index: UavsExeIndex, |
| 265 | /// Index into `string_bytes`. | 274 | /// Index into `string_bytes`. |
| ... | @@ -335,17 +344,24 @@ pub const OutputFunctionIndex = enum(u32) { | ... | @@ -335,17 +344,24 @@ pub const OutputFunctionIndex = enum(u32) { |
| 335 | return @enumFromInt(wasm.function_imports.entries.len + @intFromEnum(index)); | 344 | return @enumFromInt(wasm.function_imports.entries.len + @intFromEnum(index)); |
| 336 | } | 345 | } |
| 337 | 346 | ||
| 347 | pub fn fromIpIndex(wasm: *const Wasm, ip_index: InternPool.Index) OutputFunctionIndex { | ||
| 348 | const zcu = wasm.base.comp.zcu.?; | ||
| 349 | const ip = &zcu.intern_pool; | ||
| 350 | return switch (ip.indexToKey(ip_index)) { | ||
| 351 | .@"extern" => |ext| { | ||
| 352 | const name = wasm.getExistingString(ext.name.toSlice(ip)).?; | ||
| 353 | if (wasm.function_imports.getIndex(name)) |i| return @enumFromInt(i); | ||
| 354 | return fromFunctionIndex(wasm, FunctionIndex.fromSymbolName(wasm, name).?); | ||
| 355 | }, | ||
| 356 | else => fromResolution(wasm, .fromIpIndex(wasm, ip_index)).?, | ||
| 357 | }; | ||
| 358 | } | ||
| 359 | |||
| 338 | pub fn fromIpNav(wasm: *const Wasm, nav_index: InternPool.Nav.Index) OutputFunctionIndex { | 360 | pub fn fromIpNav(wasm: *const Wasm, nav_index: InternPool.Nav.Index) OutputFunctionIndex { |
| 339 | const zcu = wasm.base.comp.zcu.?; | 361 | const zcu = wasm.base.comp.zcu.?; |
| 340 | const ip = &zcu.intern_pool; | 362 | const ip = &zcu.intern_pool; |
| 341 | const nav = ip.getNav(nav_index); | 363 | const nav = ip.getNav(nav_index); |
| 342 | if (nav.toExtern(ip)) |ext| { | 364 | return fromIpIndex(wasm, nav.status.resolved.val); |
| 343 | const name = wasm.getExistingString(ext.name.toSlice(ip)).?; | ||
| 344 | if (wasm.function_imports.getIndex(name)) |i| return @enumFromInt(i); | ||
| 345 | return fromFunctionIndex(wasm, FunctionIndex.fromSymbolName(wasm, name).?); | ||
| 346 | } else { | ||
| 347 | return fromFunctionIndex(wasm, FunctionIndex.fromIpNav(wasm, nav_index).?); | ||
| 348 | } | ||
| 349 | } | 365 | } |
| 350 | 366 | ||
| 351 | pub fn fromTagNameType(wasm: *const Wasm, tag_type: InternPool.Index) OutputFunctionIndex { | 367 | pub fn fromTagNameType(wasm: *const Wasm, tag_type: InternPool.Index) OutputFunctionIndex { |
| ... | @@ -894,11 +910,11 @@ pub const FunctionImport = extern struct { | ... | @@ -894,11 +910,11 @@ pub const FunctionImport = extern struct { |
| 894 | pub fn fromIpNav(wasm: *const Wasm, nav_index: InternPool.Nav.Index) Resolution { | 910 | pub fn fromIpNav(wasm: *const Wasm, nav_index: InternPool.Nav.Index) Resolution { |
| 895 | const zcu = wasm.base.comp.zcu.?; | 911 | const zcu = wasm.base.comp.zcu.?; |
| 896 | const ip = &zcu.intern_pool; | 912 | const ip = &zcu.intern_pool; |
| 897 | const nav = ip.getNav(nav_index); | 913 | return fromIpIndex(wasm, ip.getNav(nav_index).status.resolved.val); |
| 898 | //log.debug("Resolution.fromIpNav {}({})", .{ nav.fqn.fmt(ip), nav_index }); | 914 | } |
| 899 | return pack(wasm, .{ | 915 | |
| 900 | .zcu_func = @enumFromInt(wasm.zcu_funcs.getIndex(nav.status.resolved.val).?), | 916 | pub fn fromIpIndex(wasm: *const Wasm, ip_index: InternPool.Index) Resolution { |
| 901 | }); | 917 | return pack(wasm, .{ .zcu_func = @enumFromInt(wasm.zcu_funcs.getIndex(ip_index).?) }); |
| 902 | } | 918 | } |
| 903 | 919 | ||
| 904 | pub fn isNavOrUnresolved(r: Resolution, wasm: *const Wasm) bool { | 920 | pub fn isNavOrUnresolved(r: Resolution, wasm: *const Wasm) bool { |
| ... | @@ -1168,7 +1184,7 @@ pub const TableImport = extern struct { | ... | @@ -1168,7 +1184,7 @@ pub const TableImport = extern struct { |
| 1168 | pub fn refType(r: Resolution, wasm: *const Wasm) std.wasm.RefType { | 1184 | pub fn refType(r: Resolution, wasm: *const Wasm) std.wasm.RefType { |
| 1169 | return switch (unpack(r)) { | 1185 | return switch (unpack(r)) { |
| 1170 | .unresolved => unreachable, | 1186 | .unresolved => unreachable, |
| 1171 | .__indirect_function_table => @panic("TODO"), | 1187 | .__indirect_function_table => .funcref, |
| 1172 | .object_table => |i| i.ptr(wasm).flags.ref_type.to(), | 1188 | .object_table => |i| i.ptr(wasm).flags.ref_type.to(), |
| 1173 | }; | 1189 | }; |
| 1174 | } | 1190 | } |
| ... | @@ -1176,7 +1192,11 @@ pub const TableImport = extern struct { | ... | @@ -1176,7 +1192,11 @@ pub const TableImport = extern struct { |
| 1176 | pub fn limits(r: Resolution, wasm: *const Wasm) std.wasm.Limits { | 1192 | pub fn limits(r: Resolution, wasm: *const Wasm) std.wasm.Limits { |
| 1177 | return switch (unpack(r)) { | 1193 | return switch (unpack(r)) { |
| 1178 | .unresolved => unreachable, | 1194 | .unresolved => unreachable, |
| 1179 | .__indirect_function_table => @panic("TODO"), | 1195 | .__indirect_function_table => .{ |
| 1196 | .flags = .{ .has_max = true, .is_shared = false }, | ||
| 1197 | .min = @intCast(wasm.indirect_function_table.entries.len + 1), | ||
| 1198 | .max = @intCast(wasm.indirect_function_table.entries.len + 1), | ||
| 1199 | }, | ||
| 1180 | .object_table => |i| i.ptr(wasm).limits(), | 1200 | .object_table => |i| i.ptr(wasm).limits(), |
| 1181 | }; | 1201 | }; |
| 1182 | } | 1202 | } |
| ... | @@ -2370,10 +2390,12 @@ pub fn deinit(wasm: *Wasm) void { | ... | @@ -2370,10 +2390,12 @@ pub fn deinit(wasm: *Wasm) void { |
| 2370 | wasm.global_exports.deinit(gpa); | 2390 | wasm.global_exports.deinit(gpa); |
| 2371 | wasm.global_imports.deinit(gpa); | 2391 | wasm.global_imports.deinit(gpa); |
| 2372 | wasm.table_imports.deinit(gpa); | 2392 | wasm.table_imports.deinit(gpa); |
| 2393 | wasm.tables.deinit(gpa); | ||
| 2373 | wasm.symbol_table.deinit(gpa); | 2394 | wasm.symbol_table.deinit(gpa); |
| 2374 | wasm.out_relocs.deinit(gpa); | 2395 | wasm.out_relocs.deinit(gpa); |
| 2375 | wasm.uav_fixups.deinit(gpa); | 2396 | wasm.uav_fixups.deinit(gpa); |
| 2376 | wasm.nav_fixups.deinit(gpa); | 2397 | wasm.nav_fixups.deinit(gpa); |
| 2398 | wasm.indirect_function_table.deinit(gpa); | ||
| 2377 | 2399 | ||
| 2378 | wasm.string_bytes.deinit(gpa); | 2400 | wasm.string_bytes.deinit(gpa); |
| 2379 | wasm.string_table.deinit(gpa); | 2401 | wasm.string_table.deinit(gpa); |
src/link/Wasm/Flush.zig+29-34| ... | @@ -33,8 +33,6 @@ missing_exports: std.AutoArrayHashMapUnmanaged(String, void) = .empty, | ... | @@ -33,8 +33,6 @@ missing_exports: std.AutoArrayHashMapUnmanaged(String, void) = .empty, |
| 33 | function_imports: std.AutoArrayHashMapUnmanaged(String, Wasm.FunctionImportId) = .empty, | 33 | function_imports: std.AutoArrayHashMapUnmanaged(String, Wasm.FunctionImportId) = .empty, |
| 34 | global_imports: std.AutoArrayHashMapUnmanaged(String, Wasm.GlobalImportId) = .empty, | 34 | global_imports: std.AutoArrayHashMapUnmanaged(String, Wasm.GlobalImportId) = .empty, |
| 35 | 35 | ||
| 36 | indirect_function_table: std.AutoArrayHashMapUnmanaged(Wasm.OutputFunctionIndex, u32) = .empty, | ||
| 37 | |||
| 38 | /// For debug purposes only. | 36 | /// For debug purposes only. |
| 39 | memory_layout_finished: bool = false, | 37 | memory_layout_finished: bool = false, |
| 40 | 38 | ||
| ... | @@ -42,7 +40,6 @@ pub fn clear(f: *Flush) void { | ... | @@ -42,7 +40,6 @@ pub fn clear(f: *Flush) void { |
| 42 | f.data_segments.clearRetainingCapacity(); | 40 | f.data_segments.clearRetainingCapacity(); |
| 43 | f.data_segment_groups.clearRetainingCapacity(); | 41 | f.data_segment_groups.clearRetainingCapacity(); |
| 44 | f.binary_bytes.clearRetainingCapacity(); | 42 | f.binary_bytes.clearRetainingCapacity(); |
| 45 | f.indirect_function_table.clearRetainingCapacity(); | ||
| 46 | f.memory_layout_finished = false; | 43 | f.memory_layout_finished = false; |
| 47 | } | 44 | } |
| 48 | 45 | ||
| ... | @@ -53,7 +50,6 @@ pub fn deinit(f: *Flush, gpa: Allocator) void { | ... | @@ -53,7 +50,6 @@ pub fn deinit(f: *Flush, gpa: Allocator) void { |
| 53 | f.missing_exports.deinit(gpa); | 50 | f.missing_exports.deinit(gpa); |
| 54 | f.function_imports.deinit(gpa); | 51 | f.function_imports.deinit(gpa); |
| 55 | f.global_imports.deinit(gpa); | 52 | f.global_imports.deinit(gpa); |
| 56 | f.indirect_function_table.deinit(gpa); | ||
| 57 | f.* = undefined; | 53 | f.* = undefined; |
| 58 | } | 54 | } |
| 59 | 55 | ||
| ... | @@ -72,10 +68,6 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { | ... | @@ -72,10 +68,6 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 72 | }; | 68 | }; |
| 73 | const is_obj = comp.config.output_mode == .Obj; | 69 | const is_obj = comp.config.output_mode == .Obj; |
| 74 | const allow_undefined = is_obj or wasm.import_symbols; | 70 | const allow_undefined = is_obj or wasm.import_symbols; |
| 75 | //const undef_byte: u8 = switch (comp.root_mod.optimize_mode) { | ||
| 76 | // .Debug, .ReleaseSafe => 0xaa, | ||
| 77 | // .ReleaseFast, .ReleaseSmall => 0x00, | ||
| 78 | //}; | ||
| 79 | 71 | ||
| 80 | if (comp.zcu) |zcu| { | 72 | if (comp.zcu) |zcu| { |
| 81 | const ip: *const InternPool = &zcu.intern_pool; // No mutations allowed! | 73 | const ip: *const InternPool = &zcu.intern_pool; // No mutations allowed! |
| ... | @@ -215,6 +207,12 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { | ... | @@ -215,6 +207,12 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 215 | wasm.functions.putAssumeCapacity(.__wasm_init_tls, {}); | 207 | wasm.functions.putAssumeCapacity(.__wasm_init_tls, {}); |
| 216 | } | 208 | } |
| 217 | 209 | ||
| 210 | try wasm.tables.ensureUnusedCapacity(gpa, 1); | ||
| 211 | |||
| 212 | if (wasm.indirect_function_table.entries.len > 0) { | ||
| 213 | wasm.tables.putAssumeCapacity(.__indirect_function_table, {}); | ||
| 214 | } | ||
| 215 | |||
| 218 | // Sort order: | 216 | // Sort order: |
| 219 | // 0. Segment category (tls, data, zero) | 217 | // 0. Segment category (tls, data, zero) |
| 220 | // 1. Segment name prefix | 218 | // 1. Segment name prefix |
| ... | @@ -642,34 +640,31 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { | ... | @@ -642,34 +640,31 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 642 | replaceVecSectionHeader(binary_bytes, header_offset, .start, @intFromEnum(func_index)); | 640 | replaceVecSectionHeader(binary_bytes, header_offset, .start, @intFromEnum(func_index)); |
| 643 | } | 641 | } |
| 644 | 642 | ||
| 645 | // element section (function table) | 643 | // element section |
| 646 | if (f.indirect_function_table.count() > 0) { | 644 | if (wasm.indirect_function_table.entries.len > 0) { |
| 647 | @panic("TODO"); | 645 | const header_offset = try reserveVecSectionHeader(gpa, binary_bytes); |
| 648 | //const header_offset = try reserveVecSectionHeader(gpa, binary_bytes); | ||
| 649 | |||
| 650 | //const table_loc = wasm.globals.get(wasm.preloaded_strings.__indirect_function_table).?; | ||
| 651 | //const table_sym = wasm.finalSymbolByLoc(table_loc); | ||
| 652 | 646 | ||
| 653 | //const flags: u32 = if (table_sym.index == 0) 0x0 else 0x02; // passive with implicit 0-index table or set table index manually | 647 | // indirect function table elements |
| 654 | //try leb.writeUleb128(binary_writer, flags); | 648 | const table_index: u32 = @intCast(wasm.tables.getIndex(.__indirect_function_table).?); |
| 655 | //if (flags == 0x02) { | 649 | // passive with implicit 0-index table or set table index manually |
| 656 | // try leb.writeUleb128(binary_writer, table_sym.index); | 650 | const flags: u32 = if (table_index == 0) 0x0 else 0x02; |
| 657 | //} | 651 | try leb.writeUleb128(binary_writer, flags); |
| 658 | //try emitInit(binary_writer, .{ .i32_const = 1 }); // We start at index 1, so unresolved function pointers are invalid | 652 | if (flags == 0x02) { |
| 659 | //if (flags == 0x02) { | 653 | try leb.writeUleb128(binary_writer, table_index); |
| 660 | // try leb.writeUleb128(binary_writer, @as(u8, 0)); // represents funcref | 654 | } |
| 661 | //} | 655 | // We start at index 1, so unresolved function pointers are invalid |
| 662 | //try leb.writeUleb128(binary_writer, @as(u32, @intCast(f.indirect_function_table.count()))); | 656 | try emitInit(binary_writer, .{ .i32_const = 1 }); |
| 663 | //var symbol_it = f.indirect_function_table.keyIterator(); | 657 | if (flags == 0x02) { |
| 664 | //while (symbol_it.next()) |symbol_loc_ptr| { | 658 | try leb.writeUleb128(binary_writer, @as(u8, 0)); // represents funcref |
| 665 | // const sym = wasm.finalSymbolByLoc(symbol_loc_ptr.*); | 659 | } |
| 666 | // assert(sym.flags.alive); | 660 | try leb.writeUleb128(binary_writer, @as(u32, @intCast(wasm.indirect_function_table.entries.len))); |
| 667 | // assert(sym.index < wasm.functions.count() + wasm.imported_functions_count); | 661 | for (wasm.indirect_function_table.keys()) |ip_index| { |
| 668 | // try leb.writeUleb128(binary_writer, sym.index); | 662 | const func_index: Wasm.OutputFunctionIndex = .fromIpIndex(wasm, ip_index); |
| 669 | //} | 663 | try leb.writeUleb128(binary_writer, @intFromEnum(func_index)); |
| 664 | } | ||
| 670 | 665 | ||
| 671 | //replaceVecSectionHeader(binary_bytes, header_offset, .element, 1); | 666 | replaceVecSectionHeader(binary_bytes, header_offset, .element, 1); |
| 672 | //section_index += 1; | 667 | section_index += 1; |
| 673 | } | 668 | } |
| 674 | 669 | ||
| 675 | // When the shared-memory option is enabled, we *must* emit the 'data count' section. | 670 | // When the shared-memory option is enabled, we *must* emit the 'data count' section. |