authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-12-30 14:15:48-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-01-15 15:11:36-08:00
loga4895f3c42e8bd7d3eba5624e4a11aae5312a085
tree00dca82208c492d01dbadd59f0100bd38d846efb
parent4fccb5ae7a3c3ad0f0ec79bf5eb628807c10eb62

wasm object parsing: fix handling of weak functions and globals


3 files changed, 76 insertions(+), 12 deletions(-)

src/Compilation.zig+1-1
......@@ -1596,7 +1596,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
15961596 .pdb_source_path = options.pdb_source_path,
15971597 .pdb_out_path = options.pdb_out_path,
15981598 .entry_addr = null, // CLI does not expose this option (yet?)
1599 .object_host_name = null, // TODO expose in the CLI
1599 .object_host_name = "env",
16001600 };
16011601
16021602 switch (options.cache_mode) {
src/link/Wasm.zig+10-2
......@@ -1113,7 +1113,7 @@ pub const GlobalImport = extern struct {
11131113 });
11141114 }
11151115
1116 fn fromObjectGlobal(wasm: *const Wasm, object_global: ObjectGlobalIndex) Resolution {
1116 pub fn fromObjectGlobal(wasm: *const Wasm, object_global: ObjectGlobalIndex) Resolution {
11171117 return pack(wasm, .{ .object_global = object_global });
11181118 }
11191119
......@@ -1154,9 +1154,13 @@ pub const GlobalImport = extern struct {
11541154 }
11551155
11561156 pub fn globalType(index: Index, wasm: *const Wasm) ObjectGlobal.Type {
1157 return value(index, wasm).flags.global_type.to();
1157 return value(index, wasm).type();
11581158 }
11591159 };
1160
1161 pub fn @"type"(gi: *const GlobalImport) ObjectGlobal.Type {
1162 return gi.flags.global_type.to();
1163 }
11601164};
11611165
11621166pub const ObjectGlobal = extern struct {
......@@ -1169,6 +1173,10 @@ pub const ObjectGlobal = extern struct {
11691173 offset: u32,
11701174 size: u32,
11711175
1176 pub fn @"type"(og: *const ObjectGlobal) Type {
1177 return og.flags.global_type.to();
1178 }
1179
11721180 pub const Type = struct {
11731181 valtype: std.wasm.Valtype,
11741182 mutable: bool,
src/link/Wasm/Object.zig+65-9
......@@ -982,9 +982,6 @@ pub fn parse(
982982 source_location.addNote(&err, "module '{s}' here", .{ptr.module_name.slice(wasm)});
983983 continue;
984984 }
985 if (symbol.flags.binding == .strong) gop.value_ptr.flags.binding = .strong;
986 if (!symbol.flags.visibility_hidden) gop.value_ptr.flags.visibility_hidden = false;
987 if (symbol.flags.no_strip) gop.value_ptr.flags.no_strip = true;
988985 } else {
989986 gop.value_ptr.* = .{
990987 .flags = symbol.flags,
......@@ -1004,7 +1001,7 @@ pub fn parse(
10041001 }
10051002 const gop = try wasm.object_global_imports.getOrPut(gpa, name);
10061003 if (gop.found_existing) {
1007 const existing_ty = gop.value_ptr.flags.global_type.to();
1004 const existing_ty = gop.value_ptr.type();
10081005 if (ptr.valtype != existing_ty.valtype) {
10091006 var err = try diags.addErrorWithNotes(2);
10101007 try err.addMsg("symbol '{s}' mismatching global types", .{name.slice(wasm)});
......@@ -1034,9 +1031,6 @@ pub fn parse(
10341031 source_location.addNote(&err, "module '{s}' here", .{ptr.module_name.slice(wasm)});
10351032 continue;
10361033 }
1037 if (symbol.flags.binding == .strong) gop.value_ptr.flags.binding = .strong;
1038 if (!symbol.flags.visibility_hidden) gop.value_ptr.flags.visibility_hidden = false;
1039 if (symbol.flags.no_strip) gop.value_ptr.flags.no_strip = true;
10401034 } else {
10411035 gop.value_ptr.* = .{
10421036 .flags = symbol.flags,
......@@ -1117,6 +1111,11 @@ pub fn parse(
11171111 gop.value_ptr.source_location = source_location;
11181112 gop.value_ptr.module_name = host_name;
11191113 gop.value_ptr.resolution = .fromObjectFunction(wasm, index);
1114 gop.value_ptr.flags = symbol.flags;
1115 continue;
1116 }
1117 if (ptr.flags.binding == .weak) {
1118 // Keep the existing one.
11201119 continue;
11211120 }
11221121 var err = try diags.addErrorWithNotes(2);
......@@ -1134,8 +1133,65 @@ pub fn parse(
11341133 };
11351134 }
11361135 },
1137
1138 inline .global, .table => |i| {
1136 .global => |index| {
1137 const ptr = index.ptr(wasm);
1138 ptr.name = symbol.name;
1139 ptr.flags = symbol.flags;
1140 if (symbol.flags.binding == .local) continue; // No participation in symbol resolution.
1141 const new_ty = ptr.type();
1142 const name = symbol.name.unwrap().?;
1143 const gop = try wasm.object_global_imports.getOrPut(gpa, name);
1144 if (gop.found_existing) {
1145 const existing_ty = gop.value_ptr.type();
1146 if (new_ty.valtype != existing_ty.valtype) {
1147 var err = try diags.addErrorWithNotes(2);
1148 try err.addMsg("symbol '{s}' mismatching global types", .{name.slice(wasm)});
1149 gop.value_ptr.source_location.addNote(&err, "type {s} here", .{@tagName(existing_ty.valtype)});
1150 source_location.addNote(&err, "type {s} here", .{@tagName(new_ty.valtype)});
1151 continue;
1152 }
1153 if (new_ty.mutable != existing_ty.mutable) {
1154 var err = try diags.addErrorWithNotes(2);
1155 try err.addMsg("symbol '{s}' mismatching global mutability", .{name.slice(wasm)});
1156 gop.value_ptr.source_location.addNote(&err, "{s} here", .{
1157 if (existing_ty.mutable) "mutable" else "not mutable",
1158 });
1159 source_location.addNote(&err, "{s} here", .{
1160 if (new_ty.mutable) "mutable" else "not mutable",
1161 });
1162 continue;
1163 }
1164 if (gop.value_ptr.resolution == .unresolved or gop.value_ptr.flags.binding == .weak) {
1165 // Intentional: if they're both weak, take the last one.
1166 gop.value_ptr.source_location = source_location;
1167 gop.value_ptr.module_name = host_name;
1168 gop.value_ptr.resolution = .fromObjectGlobal(wasm, index);
1169 gop.value_ptr.flags = symbol.flags;
1170 continue;
1171 }
1172 if (ptr.flags.binding == .weak) {
1173 // Keep the existing one.
1174 continue;
1175 }
1176 var err = try diags.addErrorWithNotes(2);
1177 try err.addMsg("symbol collision: {s}", .{name.slice(wasm)});
1178 gop.value_ptr.source_location.addNote(&err, "exported as {s} here", .{@tagName(existing_ty.valtype)});
1179 source_location.addNote(&err, "exported as {s} here", .{@tagName(new_ty.valtype)});
1180 continue;
1181 } else {
1182 gop.value_ptr.* = .{
1183 .flags = symbol.flags,
1184 .module_name = .none,
1185 .source_location = source_location,
1186 .resolution = .unresolved,
1187 };
1188 gop.value_ptr.flags.global_type = .{
1189 .valtype = .from(new_ty.valtype),
1190 .mutable = new_ty.mutable,
1191 };
1192 }
1193 },
1194 .table => |i| {
11391195 const ptr = i.ptr(wasm);
11401196 ptr.name = symbol.name;
11411197 ptr.flags = symbol.flags;