| ... | ... | @@ -1990,10 +1990,23 @@ fn initializeCallCtorsFunction(wasm: *Wasm) !void { |
| 1990 | 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 | 2008 | const symbol = loc.getSymbol(wasm); |
| 1995 | | // create type (() -> nil) as we do not have any parameters or return value. |
| 1996 | | const ty_index = try wasm.putOrGetFuncType(.{ .params = &[_]std.wasm.Valtype{}, .returns = &[_]std.wasm.Valtype{} }); |
| 2009 | const ty_index = try wasm.putOrGetFuncType(func_ty); |
| 1997 | 2010 | // create function with above type |
| 1998 | 2011 | const func_index = wasm.imported_functions_count + @intCast(u32, wasm.functions.count()); |
| 1999 | 2012 | try wasm.functions.putNoClobber( |
| ... | ... | @@ -2025,6 +2038,60 @@ fn initializeCallCtorsFunction(wasm: *Wasm) !void { |
| 2025 | 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 | 2095 | fn setupImports(wasm: *Wasm) !void { |
| 2029 | 2096 | log.debug("Merging imports", .{}); |
| 2030 | 2097 | var discarded_it = wasm.discarded.keyIterator(); |
| ... | ... | @@ -2872,6 +2939,7 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l |
| 2872 | 2939 | try wasm.mergeSections(); |
| 2873 | 2940 | try wasm.mergeTypes(); |
| 2874 | 2941 | try wasm.initializeCallCtorsFunction(); |
| 2942 | try wasm.initializeTLSFunction(); |
| 2875 | 2943 | try wasm.setupExports(); |
| 2876 | 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 | 3059 | try wasm.mergeSections(); |
| 2992 | 3060 | try wasm.mergeTypes(); |
| 2993 | 3061 | try wasm.initializeCallCtorsFunction(); |
| 3062 | try wasm.initializeTLSFunction(); |
| 2994 | 3063 | try wasm.setupExports(); |
| 2995 | 3064 | try wasm.writeToFile(enabled_features, emit_features_count, arena); |
| 2996 | 3065 | } |