| ... | @@ -1990,10 +1990,23 @@ fn initializeCallCtorsFunction(wasm: *Wasm) !void { | ... | @@ -1990,10 +1990,23 @@ fn initializeCallCtorsFunction(wasm: *Wasm) !void { |
| 1990 | try writer.writeByte(std.wasm.opcode(.end)); | 1990 | try writer.writeByte(std.wasm.opcode(.end)); |
| 1991 | } | 1991 | } |
| 1992 | | 1992 | |
| 1993 | const loc = wasm.findGlobalSymbol("__wasm_call_ctors").?; | 1993 | try wasm.createSyntheticFunction( |
| | 1994 | "__wasm_call_ctors", |
| | 1995 | std.wasm.Type{ .params = &.{}, .returns = &.{} }, |
| | 1996 | &function_body, |
| | 1997 | ); |
| | 1998 | } |
| | 1999 | |
| | 2000 | fn createSyntheticFunction( |
| | 2001 | wasm: *Wasm, |
| | 2002 | symbol_name: []const u8, |
| | 2003 | func_ty: std.wasm.Type, |
| | 2004 | function_body: *std.ArrayList(u8), |
| | 2005 | ) !void { |
| | 2006 | const loc = wasm.findGlobalSymbol(symbol_name) orelse |
| | 2007 | try wasm.createSyntheticSymbol(symbol_name, .function); |
| 1994 | const symbol = loc.getSymbol(wasm); | 2008 | const symbol = loc.getSymbol(wasm); |
| 1995 | // create type (() -> nil) as we do not have any parameters or return value. | 2009 | const ty_index = try wasm.putOrGetFuncType(func_ty); |
| 1996 | const ty_index = try wasm.putOrGetFuncType(.{ .params = &[_]std.wasm.Valtype{}, .returns = &[_]std.wasm.Valtype{} }); | | |
| 1997 | // create function with above type | 2010 | // create function with above type |
| 1998 | const func_index = wasm.imported_functions_count + @intCast(u32, wasm.functions.count()); | 2011 | const func_index = wasm.imported_functions_count + @intCast(u32, wasm.functions.count()); |
| 1999 | try wasm.functions.putNoClobber( | 2012 | try wasm.functions.putNoClobber( |
| ... | @@ -2025,6 +2038,60 @@ fn initializeCallCtorsFunction(wasm: *Wasm) !void { | ... | @@ -2025,6 +2038,60 @@ fn initializeCallCtorsFunction(wasm: *Wasm) !void { |
| 2025 | atom.offset = prev_atom.offset + prev_atom.size; | 2038 | atom.offset = prev_atom.offset + prev_atom.size; |
| 2026 | } | 2039 | } |
| 2027 | | 2040 | |
| | 2041 | fn initializeTLSFunction(wasm: *Wasm) !void { |
| | 2042 | if (!wasm.base.options.shared_memory) return; |
| | 2043 | |
| | 2044 | var function_body = std.ArrayList(u8).init(wasm.base.allocator); |
| | 2045 | defer function_body.deinit(); |
| | 2046 | const writer = function_body.writer(); |
| | 2047 | |
| | 2048 | // locals |
| | 2049 | try writer.writeByte(0); |
| | 2050 | |
| | 2051 | // If there's a TLS segment, initialize it during runtime using the bulk-memory feature |
| | 2052 | if (wasm.data_segments.getIndex(".tdata")) |data_index| { |
| | 2053 | const segment_index = wasm.data_segments.entries.items(.value)[data_index]; |
| | 2054 | const segment = wasm.segments.items[segment_index]; |
| | 2055 | |
| | 2056 | const param_local: u32 = 0; |
| | 2057 | |
| | 2058 | try writer.writeByte(std.wasm.opcode(.local_get)); |
| | 2059 | try leb.writeULEB128(writer, param_local); |
| | 2060 | |
| | 2061 | const tls_base_loc = wasm.findGlobalSymbol("__tls_base").?; |
| | 2062 | try writer.writeByte(std.wasm.opcode(.global_get)); |
| | 2063 | try leb.writeULEB128(writer, tls_base_loc.getSymbol(wasm).index); |
| | 2064 | |
| | 2065 | // load stack values for the bulk-memory operation |
| | 2066 | { |
| | 2067 | try writer.writeByte(std.wasm.opcode(.local_get)); |
| | 2068 | try leb.writeULEB128(writer, param_local); |
| | 2069 | |
| | 2070 | try writer.writeByte(std.wasm.opcode(.i32_const)); |
| | 2071 | try leb.writeULEB128(writer, @as(u32, 0)); //segment offset |
| | 2072 | |
| | 2073 | try writer.writeByte(std.wasm.opcode(.i32_const)); |
| | 2074 | try leb.writeULEB128(writer, @as(u32, segment.size)); //segment offset |
| | 2075 | } |
| | 2076 | |
| | 2077 | // perform the bulk-memory operation to initialize the data segment |
| | 2078 | try writer.writeByte(std.wasm.opcode(.prefixed)); |
| | 2079 | try leb.writeULEB128(writer, @enumToInt(std.wasm.PrefixedOpcode.memory_init)); |
| | 2080 | // segment immediate |
| | 2081 | try leb.writeULEB128(writer, @intCast(u32, data_index)); |
| | 2082 | // memory index immediate (always 0) |
| | 2083 | try leb.writeULEB128(writer, @as(u32, 0)); |
| | 2084 | } |
| | 2085 | |
| | 2086 | try writer.writeByte(std.wasm.opcode(.end)); |
| | 2087 | |
| | 2088 | try wasm.createSyntheticFunction( |
| | 2089 | "__wasm_init_tls", |
| | 2090 | std.wasm.Type{ .params = &.{.i32}, .returns = &.{} }, |
| | 2091 | &function_body, |
| | 2092 | ); |
| | 2093 | } |
| | 2094 | |
| 2028 | fn setupImports(wasm: *Wasm) !void { | 2095 | fn setupImports(wasm: *Wasm) !void { |
| 2029 | log.debug("Merging imports", .{}); | 2096 | log.debug("Merging imports", .{}); |
| 2030 | var discarded_it = wasm.discarded.keyIterator(); | 2097 | var discarded_it = wasm.discarded.keyIterator(); |
| ... | @@ -2872,6 +2939,7 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l | ... | @@ -2872,6 +2939,7 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l |
| 2872 | try wasm.mergeSections(); | 2939 | try wasm.mergeSections(); |
| 2873 | try wasm.mergeTypes(); | 2940 | try wasm.mergeTypes(); |
| 2874 | try wasm.initializeCallCtorsFunction(); | 2941 | try wasm.initializeCallCtorsFunction(); |
| | 2942 | try wasm.initializeTLSFunction(); |
| 2875 | try wasm.setupExports(); | 2943 | try wasm.setupExports(); |
| 2876 | try wasm.writeToFile(enabled_features, emit_features_count, arena); | 2944 | try wasm.writeToFile(enabled_features, emit_features_count, arena); |
| 2877 | | 2945 | |
| ... | @@ -2991,6 +3059,7 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod | ... | @@ -2991,6 +3059,7 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod |
| 2991 | try wasm.mergeSections(); | 3059 | try wasm.mergeSections(); |
| 2992 | try wasm.mergeTypes(); | 3060 | try wasm.mergeTypes(); |
| 2993 | try wasm.initializeCallCtorsFunction(); | 3061 | try wasm.initializeCallCtorsFunction(); |
| | 3062 | try wasm.initializeTLSFunction(); |
| 2994 | try wasm.setupExports(); | 3063 | try wasm.setupExports(); |
| 2995 | try wasm.writeToFile(enabled_features, emit_features_count, arena); | 3064 | try wasm.writeToFile(enabled_features, emit_features_count, arena); |
| 2996 | } | 3065 | } |