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...@@ -1596,7 +1596,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
1596 .pdb_source_path = options.pdb_source_path,1596 .pdb_source_path = options.pdb_source_path,
1597 .pdb_out_path = options.pdb_out_path,1597 .pdb_out_path = options.pdb_out_path,
1598 .entry_addr = null, // CLI does not expose this option (yet?)1598 .entry_addr = null, // CLI does not expose this option (yet?)
1599 .object_host_name = null, // TODO expose in the CLI1599 .object_host_name = "env",
1600 };1600 };
16011601
1602 switch (options.cache_mode) {1602 switch (options.cache_mode) {
src/link/Wasm.zig+10-2
...@@ -1113,7 +1113,7 @@ pub const GlobalImport = extern struct {...@@ -1113,7 +1113,7 @@ pub const GlobalImport = extern struct {
1113 });1113 });
1114 }1114 }
11151115
1116 fn fromObjectGlobal(wasm: *const Wasm, object_global: ObjectGlobalIndex) Resolution {1116 pub fn fromObjectGlobal(wasm: *const Wasm, object_global: ObjectGlobalIndex) Resolution {
1117 return pack(wasm, .{ .object_global = object_global });1117 return pack(wasm, .{ .object_global = object_global });
1118 }1118 }
11191119
...@@ -1154,9 +1154,13 @@ pub const GlobalImport = extern struct {...@@ -1154,9 +1154,13 @@ pub const GlobalImport = extern struct {
1154 }1154 }
11551155
1156 pub fn globalType(index: Index, wasm: *const Wasm) ObjectGlobal.Type {1156 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();
1158 }1158 }
1159 };1159 };
1160
1161 pub fn @"type"(gi: *const GlobalImport) ObjectGlobal.Type {
1162 return gi.flags.global_type.to();
1163 }
1160};1164};
11611165
1162pub const ObjectGlobal = extern struct {1166pub const ObjectGlobal = extern struct {
...@@ -1169,6 +1173,10 @@ pub const ObjectGlobal = extern struct {...@@ -1169,6 +1173,10 @@ pub const ObjectGlobal = extern struct {
1169 offset: u32,1173 offset: u32,
1170 size: u32,1174 size: u32,
11711175
1176 pub fn @"type"(og: *const ObjectGlobal) Type {
1177 return og.flags.global_type.to();
1178 }
1179
1172 pub const Type = struct {1180 pub const Type = struct {
1173 valtype: std.wasm.Valtype,1181 valtype: std.wasm.Valtype,
1174 mutable: bool,1182 mutable: bool,
src/link/Wasm/Object.zig+65-9
...@@ -982,9 +982,6 @@ pub fn parse(...@@ -982,9 +982,6 @@ pub fn parse(
982 source_location.addNote(&err, "module '{s}' here", .{ptr.module_name.slice(wasm)});982 source_location.addNote(&err, "module '{s}' here", .{ptr.module_name.slice(wasm)});
983 continue;983 continue;
984 }984 }
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;
988 } else {985 } else {
989 gop.value_ptr.* = .{986 gop.value_ptr.* = .{
990 .flags = symbol.flags,987 .flags = symbol.flags,
...@@ -1004,7 +1001,7 @@ pub fn parse(...@@ -1004,7 +1001,7 @@ pub fn parse(
1004 }1001 }
1005 const gop = try wasm.object_global_imports.getOrPut(gpa, name);1002 const gop = try wasm.object_global_imports.getOrPut(gpa, name);
1006 if (gop.found_existing) {1003 if (gop.found_existing) {
1007 const existing_ty = gop.value_ptr.flags.global_type.to();1004 const existing_ty = gop.value_ptr.type();
1008 if (ptr.valtype != existing_ty.valtype) {1005 if (ptr.valtype != existing_ty.valtype) {
1009 var err = try diags.addErrorWithNotes(2);1006 var err = try diags.addErrorWithNotes(2);
1010 try err.addMsg("symbol '{s}' mismatching global types", .{name.slice(wasm)});1007 try err.addMsg("symbol '{s}' mismatching global types", .{name.slice(wasm)});
...@@ -1034,9 +1031,6 @@ pub fn parse(...@@ -1034,9 +1031,6 @@ pub fn parse(
1034 source_location.addNote(&err, "module '{s}' here", .{ptr.module_name.slice(wasm)});1031 source_location.addNote(&err, "module '{s}' here", .{ptr.module_name.slice(wasm)});
1035 continue;1032 continue;
1036 }1033 }
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;
1040 } else {1034 } else {
1041 gop.value_ptr.* = .{1035 gop.value_ptr.* = .{
1042 .flags = symbol.flags,1036 .flags = symbol.flags,
...@@ -1117,6 +1111,11 @@ pub fn parse(...@@ -1117,6 +1111,11 @@ pub fn parse(
1117 gop.value_ptr.source_location = source_location;1111 gop.value_ptr.source_location = source_location;
1118 gop.value_ptr.module_name = host_name;1112 gop.value_ptr.module_name = host_name;
1119 gop.value_ptr.resolution = .fromObjectFunction(wasm, index);1113 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.
1120 continue;1119 continue;
1121 }1120 }
1122 var err = try diags.addErrorWithNotes(2);1121 var err = try diags.addErrorWithNotes(2);
...@@ -1134,8 +1133,65 @@ pub fn parse(...@@ -1134,8 +1133,65 @@ pub fn parse(
1134 };1133 };
1135 }1134 }
1136 },1135 },
11371136 .global => |index| {
1138 inline .global, .table => |i| {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| {
1139 const ptr = i.ptr(wasm);1195 const ptr = i.ptr(wasm);
1140 ptr.name = symbol.name;1196 ptr.name = symbol.name;
1141 ptr.flags = symbol.flags;1197 ptr.flags = symbol.flags;