| ... | @@ -75,6 +75,13 @@ pub const FunctionImport = struct { | ... | @@ -75,6 +75,13 @@ pub const FunctionImport = struct { |
| 75 | function_index: ScratchSpace.FuncTypeIndex, | 75 | function_index: ScratchSpace.FuncTypeIndex, |
| 76 | }; | 76 | }; |
| 77 | | 77 | |
| | 78 | pub const GlobalImport = struct { |
| | 79 | module_name: Wasm.String, |
| | 80 | name: Wasm.String, |
| | 81 | valtype: std.wasm.Valtype, |
| | 82 | mutable: bool, |
| | 83 | }; |
| | 84 | |
| 78 | pub const DataSegmentFlags = enum(u32) { active, passive, active_memidx }; | 85 | pub const DataSegmentFlags = enum(u32) { active, passive, active_memidx }; |
| 79 | | 86 | |
| 80 | pub const SubsectionType = enum(u8) { | 87 | pub const SubsectionType = enum(u8) { |
| ... | @@ -105,7 +112,7 @@ pub const Symbol = struct { | ... | @@ -105,7 +112,7 @@ pub const Symbol = struct { |
| 105 | data: Wasm.ObjectData.Index, | 112 | data: Wasm.ObjectData.Index, |
| 106 | data_import: void, | 113 | data_import: void, |
| 107 | global: Wasm.ObjectGlobalIndex, | 114 | global: Wasm.ObjectGlobalIndex, |
| 108 | global_import: Wasm.GlobalImport.Index, | 115 | global_import: ScratchSpace.GlobalImportIndex, |
| 109 | section: Wasm.ObjectSectionIndex, | 116 | section: Wasm.ObjectSectionIndex, |
| 110 | table: Wasm.ObjectTableIndex, | 117 | table: Wasm.ObjectTableIndex, |
| 111 | table_import: Wasm.TableImport.Index, | 118 | table_import: Wasm.TableImport.Index, |
| ... | @@ -116,6 +123,7 @@ pub const ScratchSpace = struct { | ... | @@ -116,6 +123,7 @@ pub const ScratchSpace = struct { |
| 116 | func_types: std.ArrayListUnmanaged(Wasm.FunctionType.Index) = .empty, | 123 | func_types: std.ArrayListUnmanaged(Wasm.FunctionType.Index) = .empty, |
| 117 | func_type_indexes: std.ArrayListUnmanaged(FuncTypeIndex) = .empty, | 124 | func_type_indexes: std.ArrayListUnmanaged(FuncTypeIndex) = .empty, |
| 118 | func_imports: std.ArrayListUnmanaged(FunctionImport) = .empty, | 125 | func_imports: std.ArrayListUnmanaged(FunctionImport) = .empty, |
| | 126 | global_imports: std.ArrayListUnmanaged(GlobalImport) = .empty, |
| 119 | symbol_table: std.ArrayListUnmanaged(Symbol) = .empty, | 127 | symbol_table: std.ArrayListUnmanaged(Symbol) = .empty, |
| 120 | segment_info: std.ArrayListUnmanaged(SegmentInfo) = .empty, | 128 | segment_info: std.ArrayListUnmanaged(SegmentInfo) = .empty, |
| 121 | exports: std.ArrayListUnmanaged(Export) = .empty, | 129 | exports: std.ArrayListUnmanaged(Export) = .empty, |
| ... | @@ -141,6 +149,15 @@ pub const ScratchSpace = struct { | ... | @@ -141,6 +149,15 @@ pub const ScratchSpace = struct { |
| 141 | } | 149 | } |
| 142 | }; | 150 | }; |
| 143 | | 151 | |
| | 152 | /// Index into `global_imports`. |
| | 153 | const GlobalImportIndex = enum(u32) { |
| | 154 | _, |
| | 155 | |
| | 156 | fn ptr(index: GlobalImportIndex, ss: *const ScratchSpace) *GlobalImport { |
| | 157 | return &ss.global_imports.items[@intFromEnum(index)]; |
| | 158 | } |
| | 159 | }; |
| | 160 | |
| 144 | /// Index into `func_types`. | 161 | /// Index into `func_types`. |
| 145 | const FuncTypeIndex = enum(u32) { | 162 | const FuncTypeIndex = enum(u32) { |
| 146 | _, | 163 | _, |
| ... | @@ -155,6 +172,7 @@ pub const ScratchSpace = struct { | ... | @@ -155,6 +172,7 @@ pub const ScratchSpace = struct { |
| 155 | ss.func_types.deinit(gpa); | 172 | ss.func_types.deinit(gpa); |
| 156 | ss.func_type_indexes.deinit(gpa); | 173 | ss.func_type_indexes.deinit(gpa); |
| 157 | ss.func_imports.deinit(gpa); | 174 | ss.func_imports.deinit(gpa); |
| | 175 | ss.global_imports.deinit(gpa); |
| 158 | ss.symbol_table.deinit(gpa); | 176 | ss.symbol_table.deinit(gpa); |
| 159 | ss.segment_info.deinit(gpa); | 177 | ss.segment_info.deinit(gpa); |
| 160 | ss.* = undefined; | 178 | ss.* = undefined; |
| ... | @@ -165,6 +183,7 @@ pub const ScratchSpace = struct { | ... | @@ -165,6 +183,7 @@ pub const ScratchSpace = struct { |
| 165 | ss.func_types.clearRetainingCapacity(); | 183 | ss.func_types.clearRetainingCapacity(); |
| 166 | ss.func_type_indexes.clearRetainingCapacity(); | 184 | ss.func_type_indexes.clearRetainingCapacity(); |
| 167 | ss.func_imports.clearRetainingCapacity(); | 185 | ss.func_imports.clearRetainingCapacity(); |
| | 186 | ss.global_imports.clearRetainingCapacity(); |
| 168 | ss.symbol_table.clearRetainingCapacity(); | 187 | ss.symbol_table.clearRetainingCapacity(); |
| 169 | ss.segment_info.clearRetainingCapacity(); | 188 | ss.segment_info.clearRetainingCapacity(); |
| 170 | } | 189 | } |
| ... | @@ -361,7 +380,7 @@ pub fn parse( | ... | @@ -361,7 +380,7 @@ pub fn parse( |
| 361 | symbol.name = function_import.ptr(ss).name.toOptional(); | 380 | symbol.name = function_import.ptr(ss).name.toOptional(); |
| 362 | } | 381 | } |
| 363 | } else { | 382 | } else { |
| 364 | symbol.pointee = .{ .function = @enumFromInt(functions_start + local_index) }; | 383 | symbol.pointee = .{ .function = @enumFromInt(functions_start + (local_index - ss.func_imports.items.len)) }; |
| 365 | const name, pos = readBytes(bytes, pos); | 384 | const name, pos = readBytes(bytes, pos); |
| 366 | symbol.name = (try wasm.internString(name)).toOptional(); | 385 | symbol.name = (try wasm.internString(name)).toOptional(); |
| 367 | } | 386 | } |
| ... | @@ -369,16 +388,16 @@ pub fn parse( | ... | @@ -369,16 +388,16 @@ pub fn parse( |
| 369 | .global => { | 388 | .global => { |
| 370 | const local_index, pos = readLeb(u32, bytes, pos); | 389 | const local_index, pos = readLeb(u32, bytes, pos); |
| 371 | if (symbol.flags.undefined) { | 390 | if (symbol.flags.undefined) { |
| 372 | const global_import: Wasm.GlobalImport.Index = @enumFromInt(global_imports_start + local_index); | 391 | const global_import: ScratchSpace.GlobalImportIndex = @enumFromInt(local_index); |
| 373 | symbol.pointee = .{ .global_import = global_import }; | 392 | symbol.pointee = .{ .global_import = global_import }; |
| 374 | if (symbol.flags.explicit_name) { | 393 | if (symbol.flags.explicit_name) { |
| 375 | const name, pos = readBytes(bytes, pos); | 394 | const name, pos = readBytes(bytes, pos); |
| 376 | symbol.name = (try wasm.internString(name)).toOptional(); | 395 | symbol.name = (try wasm.internString(name)).toOptional(); |
| 377 | } else { | 396 | } else { |
| 378 | symbol.name = global_import.key(wasm).toOptional(); | 397 | symbol.name = global_import.ptr(ss).name.toOptional(); |
| 379 | } | 398 | } |
| 380 | } else { | 399 | } else { |
| 381 | symbol.pointee = .{ .global = @enumFromInt(globals_start + local_index) }; | 400 | symbol.pointee = .{ .global = @enumFromInt(globals_start + (local_index - ss.global_imports.items.len)) }; |
| 382 | const name, pos = readBytes(bytes, pos); | 401 | const name, pos = readBytes(bytes, pos); |
| 383 | symbol.name = (try wasm.internString(name)).toOptional(); | 402 | symbol.name = (try wasm.internString(name)).toOptional(); |
| 384 | } | 403 | } |
| ... | @@ -579,16 +598,11 @@ pub fn parse( | ... | @@ -579,16 +598,11 @@ pub fn parse( |
| 579 | const valtype, pos = readEnum(std.wasm.Valtype, bytes, pos); | 598 | const valtype, pos = readEnum(std.wasm.Valtype, bytes, pos); |
| 580 | const mutable = bytes[pos] == 0x01; | 599 | const mutable = bytes[pos] == 0x01; |
| 581 | pos += 1; | 600 | pos += 1; |
| 582 | try wasm.object_global_imports.put(gpa, interned_name, .{ | 601 | try ss.global_imports.append(gpa, .{ |
| 583 | .flags = .{ | 602 | .name = interned_name, |
| 584 | .global_type = .{ | 603 | .valtype = valtype, |
| 585 | .valtype = .from(valtype), | 604 | .mutable = mutable, |
| 586 | .mutable = mutable, | 605 | .module_name = interned_module_name, |
| 587 | }, | | |
| 588 | }, | | |
| 589 | .module_name = interned_module_name.toOptional(), | | |
| 590 | .source_location = source_location, | | |
| 591 | .resolution = .unresolved, | | |
| 592 | }); | 606 | }); |
| 593 | }, | 607 | }, |
| 594 | .table => { | 608 | .table => { |
| ... | @@ -840,6 +854,61 @@ pub fn parse( | ... | @@ -840,6 +854,61 @@ pub fn parse( |
| 840 | }; | 854 | }; |
| 841 | } | 855 | } |
| 842 | }, | 856 | }, |
| | 857 | .global_import => |index| { |
| | 858 | const ptr = index.ptr(ss); |
| | 859 | const name = symbol.name.unwrap().?; |
| | 860 | if (symbol.flags.binding == .local) { |
| | 861 | diags.addParseError(path, "local symbol '{s}' references import", .{name.slice(wasm)}); |
| | 862 | continue; |
| | 863 | } |
| | 864 | const gop = try wasm.object_global_imports.getOrPut(gpa, name); |
| | 865 | if (gop.found_existing) { |
| | 866 | const existing_ty = gop.value_ptr.flags.global_type.to(); |
| | 867 | if (ptr.valtype != existing_ty.valtype) { |
| | 868 | var err = try diags.addErrorWithNotes(2); |
| | 869 | try err.addMsg("symbol '{s}' mismatching global types", .{name.slice(wasm)}); |
| | 870 | gop.value_ptr.source_location.addNote(wasm, &err, "type {s} here", .{@tagName(existing_ty.valtype)}); |
| | 871 | source_location.addNote(wasm, &err, "type {s} here", .{@tagName(ptr.valtype)}); |
| | 872 | continue; |
| | 873 | } |
| | 874 | if (ptr.mutable != existing_ty.mutable) { |
| | 875 | var err = try diags.addErrorWithNotes(2); |
| | 876 | try err.addMsg("symbol '{s}' mismatching global mutability", .{name.slice(wasm)}); |
| | 877 | gop.value_ptr.source_location.addNote(wasm, &err, "{s} here", .{ |
| | 878 | if (existing_ty.mutable) "mutable" else "not mutable", |
| | 879 | }); |
| | 880 | source_location.addNote(wasm, &err, "{s} here", .{ |
| | 881 | if (ptr.mutable) "mutable" else "not mutable", |
| | 882 | }); |
| | 883 | continue; |
| | 884 | } |
| | 885 | if (gop.value_ptr.module_name != ptr.module_name.toOptional()) { |
| | 886 | var err = try diags.addErrorWithNotes(2); |
| | 887 | try err.addMsg("function symbol '{s}' mismatching module names", .{name.slice(wasm)}); |
| | 888 | if (gop.value_ptr.module_name.slice(wasm)) |module_name| { |
| | 889 | gop.value_ptr.source_location.addNote(wasm, &err, "module '{s}' here", .{module_name}); |
| | 890 | } else { |
| | 891 | gop.value_ptr.source_location.addNote(wasm, &err, "no module here", .{}); |
| | 892 | } |
| | 893 | source_location.addNote(wasm, &err, "module '{s}' here", .{ptr.module_name.slice(wasm)}); |
| | 894 | continue; |
| | 895 | } |
| | 896 | if (symbol.flags.binding == .strong) gop.value_ptr.flags.binding = .strong; |
| | 897 | if (!symbol.flags.visibility_hidden) gop.value_ptr.flags.visibility_hidden = false; |
| | 898 | if (symbol.flags.no_strip) gop.value_ptr.flags.no_strip = true; |
| | 899 | } else { |
| | 900 | gop.value_ptr.* = .{ |
| | 901 | .flags = symbol.flags, |
| | 902 | .module_name = ptr.module_name.toOptional(), |
| | 903 | .source_location = source_location, |
| | 904 | .resolution = .unresolved, |
| | 905 | }; |
| | 906 | gop.value_ptr.flags.global_type = .{ |
| | 907 | .valtype = .from(ptr.valtype), |
| | 908 | .mutable = ptr.mutable, |
| | 909 | }; |
| | 910 | } |
| | 911 | }, |
| 843 | .function => |index| { | 912 | .function => |index| { |
| 844 | assert(!symbol.flags.undefined); | 913 | assert(!symbol.flags.undefined); |
| 845 | const ptr = index.ptr(wasm); | 914 | const ptr = index.ptr(wasm); |
| ... | @@ -882,7 +951,7 @@ pub fn parse( | ... | @@ -882,7 +951,7 @@ pub fn parse( |
| 882 | } | 951 | } |
| 883 | }, | 952 | }, |
| 884 | | 953 | |
| 885 | inline .global_import, .table_import => |i| { | 954 | .table_import => |i| { |
| 886 | const ptr = i.value(wasm); | 955 | const ptr = i.value(wasm); |
| 887 | assert(i.key(wasm).toOptional() == symbol.name); // TODO | 956 | assert(i.key(wasm).toOptional() == symbol.name); // TODO |
| 888 | ptr.flags = symbol.flags; | 957 | ptr.flags = symbol.flags; |