authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-11-15 21:51:33-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-12-06 12:15:04-07:00
logfb9a6084e28f3b732dbbce85b0706a70d848c24c
tree76f26a6189f569d4e733cad702613e6145dc7894
parentd1b3409df1804ff3182596ca41e2e2424c0918e7

zig1.c: decompress zig1.wasm.zst with zstd


3 files changed, 77 insertions(+), 644 deletions(-)

CMakeLists.txt+14-3
...@@ -181,6 +181,16 @@ set(ZIG_CONFIG_ZIG_OUT "${CMAKE_BINARY_DIR}/config.zig")...@@ -181,6 +181,16 @@ set(ZIG_CONFIG_ZIG_OUT "${CMAKE_BINARY_DIR}/config.zig")
181181
182set(STAGE1_SOURCES182set(STAGE1_SOURCES
183 "${CMAKE_SOURCE_DIR}/stage1/zig1.c"183 "${CMAKE_SOURCE_DIR}/stage1/zig1.c"
184 "${CMAKE_SOURCE_DIR}/stage1/zstd/lib/decompress/huf_decompress.c"
185 "${CMAKE_SOURCE_DIR}/stage1/zstd/lib/decompress/zstd_ddict.c"
186 "${CMAKE_SOURCE_DIR}/stage1/zstd/lib/decompress/zstd_decompress.c"
187 "${CMAKE_SOURCE_DIR}/stage1/zstd/lib/decompress/zstd_decompress_block.c"
188 "${CMAKE_SOURCE_DIR}/stage1/zstd/lib/common/entropy_common.c"
189 "${CMAKE_SOURCE_DIR}/stage1/zstd/lib/common/error_private.c"
190 "${CMAKE_SOURCE_DIR}/stage1/zstd/lib/common/fse_decompress.c"
191 "${CMAKE_SOURCE_DIR}/stage1/zstd/lib/common/pool.c"
192 "${CMAKE_SOURCE_DIR}/stage1/zstd/lib/common/xxhash.c"
193 "${CMAKE_SOURCE_DIR}/stage1/zstd/lib/common/zstd_common.c"
184)194)
185set(ZIG_CPP_SOURCES195set(ZIG_CPP_SOURCES
186 # These are planned to stay even when we are self-hosted.196 # These are planned to stay even when we are self-hosted.
...@@ -710,14 +720,15 @@ endif()...@@ -710,14 +720,15 @@ endif()
710add_executable(zig1 ${STAGE1_SOURCES})720add_executable(zig1 ${STAGE1_SOURCES})
711set_target_properties(zig1 PROPERTIES COMPILE_FLAGS ${ZIG1_COMPILE_FLAGS})721set_target_properties(zig1 PROPERTIES COMPILE_FLAGS ${ZIG1_COMPILE_FLAGS})
712target_link_libraries(zig1 LINK_PUBLIC m)722target_link_libraries(zig1 LINK_PUBLIC m)
713723target_include_directories(zig1 PUBLIC "${CMAKE_SOURCE_DIR}/stage1/zstd/lib")
724target_compile_definitions(zig1 PRIVATE ZSTD_DISABLE_ASM)
714725
715set(ZIG2_C_SOURCE "${CMAKE_BINARY_DIR}/zig2.c")726set(ZIG2_C_SOURCE "${CMAKE_BINARY_DIR}/zig2.c")
716set(BUILD_ZIG2_ARGS727set(BUILD_ZIG2_ARGS
717 "${CMAKE_SOURCE_DIR}/lib"728 "${CMAKE_SOURCE_DIR}/lib"
718 "${CMAKE_BINARY_DIR}"729 "${CMAKE_BINARY_DIR}"
719 zig2730 zig2
720 "${CMAKE_SOURCE_DIR}/stage1/zig1.wasm"731 "${CMAKE_SOURCE_DIR}/stage1/zig1.wasm.zst"
721 build-exe src/main.zig -ofmt=c -lc732 build-exe src/main.zig -ofmt=c -lc
722 -target x86_64-linux-musl # TODO: autodetect in zig1.c733 -target x86_64-linux-musl # TODO: autodetect in zig1.c
723 -OReleaseFast734 -OReleaseFast
...@@ -736,7 +747,7 @@ set(BUILD_COMPILER_RT_ARGS...@@ -736,7 +747,7 @@ set(BUILD_COMPILER_RT_ARGS
736 "${CMAKE_SOURCE_DIR}/lib"747 "${CMAKE_SOURCE_DIR}/lib"
737 "${CMAKE_BINARY_DIR}"748 "${CMAKE_BINARY_DIR}"
738 compiler_rt749 compiler_rt
739 "${CMAKE_SOURCE_DIR}/stage1/zig1.wasm"750 "${CMAKE_SOURCE_DIR}/stage1/zig1.wasm.zst"
740 build-obj lib/compiler_rt.zig -ofmt=c751 build-obj lib/compiler_rt.zig -ofmt=c
741 -target x86_64-linux-musl # TODO: autodetect in zig1.c752 -target x86_64-linux-musl # TODO: autodetect in zig1.c
742 -OReleaseFast753 -OReleaseFast
stage1/zig1.c+63-56
...@@ -20,6 +20,8 @@...@@ -20,6 +20,8 @@
20#include <sys/random.h>20#include <sys/random.h>
21#endif21#endif
2222
23#include <zstd.h>
24
23enum wasi_errno_t {25enum wasi_errno_t {
24 WASI_ESUCCESS = 0,26 WASI_ESUCCESS = 0,
25 WASI_E2BIG = 1,27 WASI_E2BIG = 1,
...@@ -4122,7 +4124,12 @@ int main(int argc, char **argv) {...@@ -4122,7 +4124,12 @@ int main(int argc, char **argv) {
41224124
4123 new_argv[new_argv_i] = NULL;4125 new_argv[new_argv_i] = NULL;
41244126
4125 const struct ByteSlice mod = read_file_alloc(wasm_file);4127 const struct ByteSlice compressed_bytes = read_file_alloc(wasm_file);
4128
4129 const size_t max_uncompressed_size = 2500000;
4130 char *mod_ptr = arena_alloc(max_uncompressed_size);
4131 size_t mod_len = ZSTD_decompress(mod_ptr, max_uncompressed_size,
4132 compressed_bytes.ptr, compressed_bytes.len);
41264133
4127 int cwd = err_wrap("opening cwd", open(".", O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_PATH));4134 int cwd = err_wrap("opening cwd", open(".", O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_PATH));
4128 int zig_lib_dir = err_wrap("opening zig lib dir", open(zig_lib_dir_path, O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_PATH));4135 int zig_lib_dir = err_wrap("opening zig lib dir", open(zig_lib_dir_path, O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_PATH));
...@@ -4136,22 +4143,22 @@ int main(int argc, char **argv) {...@@ -4136,22 +4143,22 @@ int main(int argc, char **argv) {
41364143
4137 uint32_t i = 0;4144 uint32_t i = 0;
41384145
4139 if (mod.ptr[0] != 0 || mod.ptr[1] != 'a' || mod.ptr[2] != 's' || mod.ptr[3] != 'm') {4146 if (mod_ptr[0] != 0 || mod_ptr[1] != 'a' || mod_ptr[2] != 's' || mod_ptr[3] != 'm') {
4140 panic("bad magic");4147 panic("bad magic");
4141 }4148 }
4142 i += 4;4149 i += 4;
41434150
4144 uint32_t version = read_u32_le(mod.ptr + i);4151 uint32_t version = read_u32_le(mod_ptr + i);
4145 i += 4;4152 i += 4;
4146 if (version != 1) panic("bad wasm version");4153 if (version != 1) panic("bad wasm version");
41474154
4148 uint32_t section_starts[13];4155 uint32_t section_starts[13];
4149 memset(&section_starts, 0, sizeof(uint32_t) * 13);4156 memset(&section_starts, 0, sizeof(uint32_t) * 13);
41504157
4151 while (i < mod.len) {4158 while (i < mod_len) {
4152 uint8_t section_id = mod.ptr[i];4159 uint8_t section_id = mod_ptr[i];
4153 i += 1;4160 i += 1;
4154 uint32_t section_len = read32_uleb128(mod.ptr, &i);4161 uint32_t section_len = read32_uleb128(mod_ptr, &i);
4155 section_starts[section_id] = i;4162 section_starts[section_id] = i;
4156 i += section_len;4163 i += section_len;
4157 }4164 }
...@@ -4160,18 +4167,18 @@ int main(int argc, char **argv) {...@@ -4160,18 +4167,18 @@ int main(int argc, char **argv) {
4160 struct TypeInfo *types;4167 struct TypeInfo *types;
4161 {4168 {
4162 i = section_starts[Section_type];4169 i = section_starts[Section_type];
4163 uint32_t types_len = read32_uleb128(mod.ptr, &i);4170 uint32_t types_len = read32_uleb128(mod_ptr, &i);
4164 types = arena_alloc(sizeof(struct TypeInfo) * types_len);4171 types = arena_alloc(sizeof(struct TypeInfo) * types_len);
4165 for (size_t type_i = 0; type_i < types_len; type_i += 1) {4172 for (size_t type_i = 0; type_i < types_len; type_i += 1) {
4166 struct TypeInfo *info = &types[type_i];4173 struct TypeInfo *info = &types[type_i];
4167 if (mod.ptr[i] != 0x60) panic("bad type byte");4174 if (mod_ptr[i] != 0x60) panic("bad type byte");
4168 i += 1;4175 i += 1;
41694176
4170 info->param_count = read32_uleb128(mod.ptr, &i);4177 info->param_count = read32_uleb128(mod_ptr, &i);
4171 if (info->param_count > 32) panic("found a type with over 32 parameters");4178 if (info->param_count > 32) panic("found a type with over 32 parameters");
4172 info->param_types = 0;4179 info->param_types = 0;
4173 for (uint32_t param_i = 0; param_i < info->param_count; param_i += 1) {4180 for (uint32_t param_i = 0; param_i < info->param_count; param_i += 1) {
4174 int64_t param_type = read64_ileb128(mod.ptr, &i);4181 int64_t param_type = read64_ileb128(mod_ptr, &i);
4175 switch (param_type) {4182 switch (param_type) {
4176 case -1: case -3: bs_unset(&info->param_types, param_i); break;4183 case -1: case -3: bs_unset(&info->param_types, param_i); break;
4177 case -2: case -4: bs_set(&info->param_types, param_i); break;4184 case -2: case -4: bs_set(&info->param_types, param_i); break;
...@@ -4179,10 +4186,10 @@ int main(int argc, char **argv) {...@@ -4179,10 +4186,10 @@ int main(int argc, char **argv) {
4179 }4186 }
4180 }4187 }
41814188
4182 info->result_count = read32_uleb128(mod.ptr, &i);4189 info->result_count = read32_uleb128(mod_ptr, &i);
4183 info->result_types = 0;4190 info->result_types = 0;
4184 for (uint32_t result_i = 0; result_i < info->result_count; result_i += 1) {4191 for (uint32_t result_i = 0; result_i < info->result_count; result_i += 1) {
4185 int64_t result_type = read64_ileb128(mod.ptr, &i);4192 int64_t result_type = read64_ileb128(mod_ptr, &i);
4186 switch (result_type) {4193 switch (result_type) {
4187 case -1: case -3: bs_unset(&info->result_types, result_i); break;4194 case -1: case -3: bs_unset(&info->result_types, result_i); break;
4188 case -2: case -4: bs_set(&info->result_types, result_i); break;4195 case -2: case -4: bs_set(&info->result_types, result_i); break;
...@@ -4197,18 +4204,18 @@ int main(int argc, char **argv) {...@@ -4197,18 +4204,18 @@ int main(int argc, char **argv) {
4197 uint32_t imports_len;4204 uint32_t imports_len;
4198 {4205 {
4199 i = section_starts[Section_import];4206 i = section_starts[Section_import];
4200 imports_len = read32_uleb128(mod.ptr, &i);4207 imports_len = read32_uleb128(mod_ptr, &i);
4201 imports = arena_alloc(sizeof(struct Import) * imports_len);4208 imports = arena_alloc(sizeof(struct Import) * imports_len);
4202 for (size_t imp_i = 0; imp_i < imports_len; imp_i += 1) {4209 for (size_t imp_i = 0; imp_i < imports_len; imp_i += 1) {
4203 struct Import *imp = &imports[imp_i];4210 struct Import *imp = &imports[imp_i];
42044211
4205 struct ByteSlice mod_name = read_name(mod.ptr, &i);4212 struct ByteSlice mod_name = read_name(mod_ptr, &i);
4206 if (mod_name.len == strlen("wasi_snapshot_preview1") &&4213 if (mod_name.len == strlen("wasi_snapshot_preview1") &&
4207 memcmp(mod_name.ptr, "wasi_snapshot_preview1", mod_name.len) == 0) {4214 memcmp(mod_name.ptr, "wasi_snapshot_preview1", mod_name.len) == 0) {
4208 imp->mod = ImpMod_wasi_snapshot_preview1;4215 imp->mod = ImpMod_wasi_snapshot_preview1;
4209 } else panic("unknown import module");4216 } else panic("unknown import module");
42104217
4211 struct ByteSlice sym_name = read_name(mod.ptr, &i);4218 struct ByteSlice sym_name = read_name(mod_ptr, &i);
4212 if (sym_name.len == strlen("args_get") &&4219 if (sym_name.len == strlen("args_get") &&
4213 memcmp(sym_name.ptr, "args_get", sym_name.len) == 0) {4220 memcmp(sym_name.ptr, "args_get", sym_name.len) == 0) {
4214 imp->name = ImpName_args_get;4221 imp->name = ImpName_args_get;
...@@ -4292,9 +4299,9 @@ int main(int argc, char **argv) {...@@ -4292,9 +4299,9 @@ int main(int argc, char **argv) {
4292 imp->name = ImpName_random_get;4299 imp->name = ImpName_random_get;
4293 } else panic("unknown import name");4300 } else panic("unknown import name");
42944301
4295 uint32_t desc = read32_uleb128(mod.ptr, &i);4302 uint32_t desc = read32_uleb128(mod_ptr, &i);
4296 if (desc != 0) panic("external kind not function");4303 if (desc != 0) panic("external kind not function");
4297 imp->type_idx = read32_uleb128(mod.ptr, &i);4304 imp->type_idx = read32_uleb128(mod_ptr, &i);
4298 }4305 }
4299 }4306 }
43004307
...@@ -4302,11 +4309,11 @@ int main(int argc, char **argv) {...@@ -4302,11 +4309,11 @@ int main(int argc, char **argv) {
4302 uint32_t start_fn_idx;4309 uint32_t start_fn_idx;
4303 {4310 {
4304 i = section_starts[Section_export];4311 i = section_starts[Section_export];
4305 uint32_t count = read32_uleb128(mod.ptr, &i);4312 uint32_t count = read32_uleb128(mod_ptr, &i);
4306 for (; count > 0; count -= 1) {4313 for (; count > 0; count -= 1) {
4307 struct ByteSlice name = read_name(mod.ptr, &i);4314 struct ByteSlice name = read_name(mod_ptr, &i);
4308 uint32_t desc = read32_uleb128(mod.ptr, &i);4315 uint32_t desc = read32_uleb128(mod_ptr, &i);
4309 start_fn_idx = read32_uleb128(mod.ptr, &i);4316 start_fn_idx = read32_uleb128(mod_ptr, &i);
4310 if (desc == 0 && name.len == strlen("_start") &&4317 if (desc == 0 && name.len == strlen("_start") &&
4311 memcmp(name.ptr, "_start", name.len) == 0)4318 memcmp(name.ptr, "_start", name.len) == 0)
4312 {4319 {
...@@ -4321,11 +4328,11 @@ int main(int argc, char **argv) {...@@ -4321,11 +4328,11 @@ int main(int argc, char **argv) {
4321 uint32_t functions_len;4328 uint32_t functions_len;
4322 {4329 {
4323 i = section_starts[Section_function];4330 i = section_starts[Section_function];
4324 functions_len = read32_uleb128(mod.ptr, &i);4331 functions_len = read32_uleb128(mod_ptr, &i);
4325 functions = arena_alloc(sizeof(struct Function) * functions_len);4332 functions = arena_alloc(sizeof(struct Function) * functions_len);
4326 for (size_t func_i = 0; func_i < functions_len; func_i += 1) {4333 for (size_t func_i = 0; func_i < functions_len; func_i += 1) {
4327 struct Function *func = &functions[func_i];4334 struct Function *func = &functions[func_i];
4328 func->type_idx = read32_uleb128(mod.ptr, &i);4335 func->type_idx = read32_uleb128(mod_ptr, &i);
4329 }4336 }
4330 }4337 }
43314338
...@@ -4333,18 +4340,18 @@ int main(int argc, char **argv) {...@@ -4333,18 +4340,18 @@ int main(int argc, char **argv) {
4333 uint64_t *globals;4340 uint64_t *globals;
4334 {4341 {
4335 i = section_starts[Section_global];4342 i = section_starts[Section_global];
4336 uint32_t globals_len = read32_uleb128(mod.ptr, &i);4343 uint32_t globals_len = read32_uleb128(mod_ptr, &i);
4337 globals = arena_alloc(sizeof(uint64_t) * globals_len);4344 globals = arena_alloc(sizeof(uint64_t) * globals_len);
4338 for (size_t glob_i = 0; glob_i < globals_len; glob_i += 1) {4345 for (size_t glob_i = 0; glob_i < globals_len; glob_i += 1) {
4339 uint64_t *global = &globals[glob_i];4346 uint64_t *global = &globals[glob_i];
4340 uint32_t content_type = read32_uleb128(mod.ptr, &i);4347 uint32_t content_type = read32_uleb128(mod_ptr, &i);
4341 uint32_t mutability = read32_uleb128(mod.ptr, &i);4348 uint32_t mutability = read32_uleb128(mod_ptr, &i);
4342 if (mutability != 1) panic("expected mutable global");4349 if (mutability != 1) panic("expected mutable global");
4343 if (content_type != 0x7f) panic("unexpected content type");4350 if (content_type != 0x7f) panic("unexpected content type");
4344 uint8_t opcode = mod.ptr[i];4351 uint8_t opcode = mod_ptr[i];
4345 i += 1;4352 i += 1;
4346 if (opcode != WasmOp_i32_const) panic("expected i32_const op");4353 if (opcode != WasmOp_i32_const) panic("expected i32_const op");
4347 uint32_t init = read32_ileb128(mod.ptr, &i);4354 uint32_t init = read32_ileb128(mod_ptr, &i);
4348 *global = (uint32_t)init;4355 *global = (uint32_t)init;
4349 }4356 }
4350 }4357 }
...@@ -4353,26 +4360,26 @@ int main(int argc, char **argv) {...@@ -4353,26 +4360,26 @@ int main(int argc, char **argv) {
4353 uint32_t memory_len;4360 uint32_t memory_len;
4354 {4361 {
4355 i = section_starts[Section_memory];4362 i = section_starts[Section_memory];
4356 uint32_t memories_len = read32_uleb128(mod.ptr, &i);4363 uint32_t memories_len = read32_uleb128(mod_ptr, &i);
4357 if (memories_len != 1) panic("unexpected memory count");4364 if (memories_len != 1) panic("unexpected memory count");
4358 uint32_t flags = read32_uleb128(mod.ptr, &i);4365 uint32_t flags = read32_uleb128(mod_ptr, &i);
4359 (void)flags;4366 (void)flags;
4360 memory_len = read32_uleb128(mod.ptr, &i) * wasm_page_size;4367 memory_len = read32_uleb128(mod_ptr, &i) * wasm_page_size;
43614368
4362 i = section_starts[Section_data];4369 i = section_starts[Section_data];
4363 uint32_t datas_count = read32_uleb128(mod.ptr, &i);4370 uint32_t datas_count = read32_uleb128(mod_ptr, &i);
4364 for (; datas_count > 0; datas_count -= 1) {4371 for (; datas_count > 0; datas_count -= 1) {
4365 uint32_t mode = read32_uleb128(mod.ptr, &i);4372 uint32_t mode = read32_uleb128(mod_ptr, &i);
4366 if (mode != 0) panic("expected mode 0");4373 if (mode != 0) panic("expected mode 0");
4367 enum WasmOp opcode = mod.ptr[i];4374 enum WasmOp opcode = mod_ptr[i];
4368 i += 1;4375 i += 1;
4369 if (opcode != WasmOp_i32_const) panic("expected opcode i32_const");4376 if (opcode != WasmOp_i32_const) panic("expected opcode i32_const");
4370 uint32_t offset = read32_uleb128(mod.ptr, &i);4377 uint32_t offset = read32_uleb128(mod_ptr, &i);
4371 enum WasmOp end = mod.ptr[i];4378 enum WasmOp end = mod_ptr[i];
4372 if (end != WasmOp_end) panic("expected end opcode");4379 if (end != WasmOp_end) panic("expected end opcode");
4373 i += 1;4380 i += 1;
4374 uint32_t bytes_len = read32_uleb128(mod.ptr, &i);4381 uint32_t bytes_len = read32_uleb128(mod_ptr, &i);
4375 memcpy(memory + offset, mod.ptr + i, bytes_len);4382 memcpy(memory + offset, mod_ptr + i, bytes_len);
4376 i += bytes_len;4383 i += bytes_len;
4377 }4384 }
4378 }4385 }
...@@ -4380,37 +4387,37 @@ int main(int argc, char **argv) {...@@ -4380,37 +4387,37 @@ int main(int argc, char **argv) {
4380 uint32_t *table = NULL;4387 uint32_t *table = NULL;
4381 {4388 {
4382 i = section_starts[Section_table];4389 i = section_starts[Section_table];
4383 uint32_t table_count = read32_uleb128(mod.ptr, &i);4390 uint32_t table_count = read32_uleb128(mod_ptr, &i);
4384 if (table_count > 1) {4391 if (table_count > 1) {
4385 panic("expected only one table section");4392 panic("expected only one table section");
4386 } else if (table_count == 1) {4393 } else if (table_count == 1) {
4387 uint32_t element_type = read32_uleb128(mod.ptr, &i);4394 uint32_t element_type = read32_uleb128(mod_ptr, &i);
4388 (void)element_type;4395 (void)element_type;
4389 uint32_t has_max = read32_uleb128(mod.ptr, &i);4396 uint32_t has_max = read32_uleb128(mod_ptr, &i);
4390 if (has_max != 1) panic("expected has_max==1");4397 if (has_max != 1) panic("expected has_max==1");
4391 uint32_t initial = read32_uleb128(mod.ptr, &i);4398 uint32_t initial = read32_uleb128(mod_ptr, &i);
4392 (void)initial;4399 (void)initial;
4393 uint32_t maximum = read32_uleb128(mod.ptr, &i);4400 uint32_t maximum = read32_uleb128(mod_ptr, &i);
43944401
4395 i = section_starts[Section_element];4402 i = section_starts[Section_element];
4396 uint32_t element_section_count = read32_uleb128(mod.ptr, &i);4403 uint32_t element_section_count = read32_uleb128(mod_ptr, &i);
4397 if (element_section_count != 1) panic("expected one element section");4404 if (element_section_count != 1) panic("expected one element section");
4398 uint32_t flags = read32_uleb128(mod.ptr, &i);4405 uint32_t flags = read32_uleb128(mod_ptr, &i);
4399 (void)flags;4406 (void)flags;
4400 enum WasmOp opcode = mod.ptr[i];4407 enum WasmOp opcode = mod_ptr[i];
4401 i += 1;4408 i += 1;
4402 if (opcode != WasmOp_i32_const) panic("expected op i32_const");4409 if (opcode != WasmOp_i32_const) panic("expected op i32_const");
4403 uint32_t offset = read32_uleb128(mod.ptr, &i);4410 uint32_t offset = read32_uleb128(mod_ptr, &i);
4404 enum WasmOp end = mod.ptr[i];4411 enum WasmOp end = mod_ptr[i];
4405 if (end != WasmOp_end) panic("expected op end");4412 if (end != WasmOp_end) panic("expected op end");
4406 i += 1;4413 i += 1;
4407 uint32_t elem_count = read32_uleb128(mod.ptr, &i);4414 uint32_t elem_count = read32_uleb128(mod_ptr, &i);
44084415
4409 table = arena_alloc(sizeof(uint32_t) * maximum);4416 table = arena_alloc(sizeof(uint32_t) * maximum);
4410 memset(table, 0, sizeof(uint32_t) * maximum);4417 memset(table, 0, sizeof(uint32_t) * maximum);
44114418
4412 for (uint32_t elem_i = 0; elem_i < elem_count; elem_i += 1) {4419 for (uint32_t elem_i = 0; elem_i < elem_count; elem_i += 1) {
4413 table[elem_i + offset] = read32_uleb128(mod.ptr, &i);4420 table[elem_i + offset] = read32_uleb128(mod_ptr, &i);
4414 }4421 }
4415 }4422 }
4416 }4423 }
...@@ -4420,7 +4427,7 @@ int main(int argc, char **argv) {...@@ -4420,7 +4427,7 @@ int main(int argc, char **argv) {
4420 memset(&vm, 0xaa, sizeof(struct VirtualMachine)); // to match the zig version4427 memset(&vm, 0xaa, sizeof(struct VirtualMachine)); // to match the zig version
4421#endif4428#endif
4422 vm.stack = arena_alloc(sizeof(uint64_t) * 10000000),4429 vm.stack = arena_alloc(sizeof(uint64_t) * 10000000),
4423 vm.mod_ptr = mod.ptr;4430 vm.mod_ptr = mod_ptr;
4424 vm.opcodes = arena_alloc(2000000);4431 vm.opcodes = arena_alloc(2000000);
4425 vm.operands = arena_alloc(sizeof(uint32_t) * 2000000);4432 vm.operands = arena_alloc(sizeof(uint32_t) * 2000000);
4426 vm.stack_top = 0;4433 vm.stack_top = 0;
...@@ -4436,14 +4443,14 @@ int main(int argc, char **argv) {...@@ -4436,14 +4443,14 @@ int main(int argc, char **argv) {
44364443
4437 {4444 {
4438 uint32_t code_i = section_starts[Section_code];4445 uint32_t code_i = section_starts[Section_code];
4439 uint32_t codes_len = read32_uleb128(mod.ptr, &code_i);4446 uint32_t codes_len = read32_uleb128(mod_ptr, &code_i);
4440 if (codes_len != functions_len) panic("code/function length mismatch");4447 if (codes_len != functions_len) panic("code/function length mismatch");
4441 struct ProgramCounter pc;4448 struct ProgramCounter pc;
4442 pc.opcode = 0;4449 pc.opcode = 0;
4443 pc.operand = 0;4450 pc.operand = 0;
4444 for (uint32_t func_i = 0; func_i < functions_len; func_i += 1) {4451 for (uint32_t func_i = 0; func_i < functions_len; func_i += 1) {
4445 struct Function *func = &functions[func_i];4452 struct Function *func = &functions[func_i];
4446 uint32_t size = read32_uleb128(mod.ptr, &code_i);4453 uint32_t size = read32_uleb128(mod_ptr, &code_i);
4447 uint32_t code_begin = code_i;4454 uint32_t code_begin = code_i;
44484455
4449 struct TypeInfo *type_info = &vm.types[func->type_idx];4456 struct TypeInfo *type_info = &vm.types[func->type_idx];
...@@ -4451,11 +4458,11 @@ int main(int argc, char **argv) {...@@ -4451,11 +4458,11 @@ int main(int argc, char **argv) {
4451 func->local_types = malloc(sizeof(uint32_t) * ((type_info->param_count + func->locals_count + 31) / 32));4458 func->local_types = malloc(sizeof(uint32_t) * ((type_info->param_count + func->locals_count + 31) / 32));
4452 func->local_types[0] = type_info->param_types;4459 func->local_types[0] = type_info->param_types;
44534460
4454 for (uint32_t local_sets_count = read32_uleb128(mod.ptr, &code_i);4461 for (uint32_t local_sets_count = read32_uleb128(mod_ptr, &code_i);
4455 local_sets_count > 0; local_sets_count -= 1)4462 local_sets_count > 0; local_sets_count -= 1)
4456 {4463 {
4457 uint32_t set_count = read32_uleb128(mod.ptr, &code_i);4464 uint32_t set_count = read32_uleb128(mod_ptr, &code_i);
4458 int64_t local_type = read64_ileb128(mod.ptr, &code_i);4465 int64_t local_type = read64_ileb128(mod_ptr, &code_i);
44594466
4460 uint32_t i = type_info->param_count + func->locals_count;4467 uint32_t i = type_info->param_count + func->locals_count;
4461 func->locals_count += set_count;4468 func->locals_count += set_count;
stage1/zstd/lib/decompress/huf_decompress_amd64.S deleted-585
...@@ -1,585 +0,0 @@
1/*
2 * Copyright (c) Facebook, Inc.
3 * All rights reserved.
4 *
5 * This source code is licensed under both the BSD-style license (found in the
6 * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7 * in the COPYING file in the root directory of this source tree).
8 * You may select, at your option, one of the above-listed licenses.
9 */
10
11#include "../common/portability_macros.h"
12
13/* Stack marking
14 * ref: https://wiki.gentoo.org/wiki/Hardened/GNU_stack_quickstart
15 */
16#if defined(__ELF__) && defined(__GNUC__)
17.section .note.GNU-stack,"",%progbits
18#endif
19
20#if ZSTD_ENABLE_ASM_X86_64_BMI2
21
22/* Calling convention:
23 *
24 * %rdi contains the first argument: HUF_DecompressAsmArgs*.
25 * %rbp isn't maintained (no frame pointer).
26 * %rsp contains the stack pointer that grows down.
27 * No red-zone is assumed, only addresses >= %rsp are used.
28 * All register contents are preserved.
29 *
30 * TODO: Support Windows calling convention.
31 */
32
33ZSTD_HIDE_ASM_FUNCTION(HUF_decompress4X1_usingDTable_internal_bmi2_asm_loop)
34ZSTD_HIDE_ASM_FUNCTION(HUF_decompress4X2_usingDTable_internal_bmi2_asm_loop)
35ZSTD_HIDE_ASM_FUNCTION(_HUF_decompress4X2_usingDTable_internal_bmi2_asm_loop)
36ZSTD_HIDE_ASM_FUNCTION(_HUF_decompress4X1_usingDTable_internal_bmi2_asm_loop)
37.global HUF_decompress4X1_usingDTable_internal_bmi2_asm_loop
38.global HUF_decompress4X2_usingDTable_internal_bmi2_asm_loop
39.global _HUF_decompress4X1_usingDTable_internal_bmi2_asm_loop
40.global _HUF_decompress4X2_usingDTable_internal_bmi2_asm_loop
41.text
42
43/* Sets up register mappings for clarity.
44 * op[], bits[], dtable & ip[0] each get their own register.
45 * ip[1,2,3] & olimit alias var[].
46 * %rax is a scratch register.
47 */
48
49#define op0 rsi
50#define op1 rbx
51#define op2 rcx
52#define op3 rdi
53
54#define ip0 r8
55#define ip1 r9
56#define ip2 r10
57#define ip3 r11
58
59#define bits0 rbp
60#define bits1 rdx
61#define bits2 r12
62#define bits3 r13
63#define dtable r14
64#define olimit r15
65
66/* var[] aliases ip[1,2,3] & olimit
67 * ip[1,2,3] are saved every iteration.
68 * olimit is only used in compute_olimit.
69 */
70#define var0 r15
71#define var1 r9
72#define var2 r10
73#define var3 r11
74
75/* 32-bit var registers */
76#define vard0 r15d
77#define vard1 r9d
78#define vard2 r10d
79#define vard3 r11d
80
81/* Calls X(N) for each stream 0, 1, 2, 3. */
82#define FOR_EACH_STREAM(X) \
83 X(0); \
84 X(1); \
85 X(2); \
86 X(3)
87
88/* Calls X(N, idx) for each stream 0, 1, 2, 3. */
89#define FOR_EACH_STREAM_WITH_INDEX(X, idx) \
90 X(0, idx); \
91 X(1, idx); \
92 X(2, idx); \
93 X(3, idx)
94
95/* Define both _HUF_* & HUF_* symbols because MacOS
96 * C symbols are prefixed with '_' & Linux symbols aren't.
97 */
98_HUF_decompress4X1_usingDTable_internal_bmi2_asm_loop:
99HUF_decompress4X1_usingDTable_internal_bmi2_asm_loop:
100 /* Save all registers - even if they are callee saved for simplicity. */
101 push %rax
102 push %rbx
103 push %rcx
104 push %rdx
105 push %rbp
106 push %rsi
107 push %rdi
108 push %r8
109 push %r9
110 push %r10
111 push %r11
112 push %r12
113 push %r13
114 push %r14
115 push %r15
116
117 /* Read HUF_DecompressAsmArgs* args from %rax */
118 movq %rdi, %rax
119 movq 0(%rax), %ip0
120 movq 8(%rax), %ip1
121 movq 16(%rax), %ip2
122 movq 24(%rax), %ip3
123 movq 32(%rax), %op0
124 movq 40(%rax), %op1
125 movq 48(%rax), %op2
126 movq 56(%rax), %op3
127 movq 64(%rax), %bits0
128 movq 72(%rax), %bits1
129 movq 80(%rax), %bits2
130 movq 88(%rax), %bits3
131 movq 96(%rax), %dtable
132 push %rax /* argument */
133 push 104(%rax) /* ilimit */
134 push 112(%rax) /* oend */
135 push %olimit /* olimit space */
136
137 subq $24, %rsp
138
139.L_4X1_compute_olimit:
140 /* Computes how many iterations we can do safely
141 * %r15, %rax may be clobbered
142 * rbx, rdx must be saved
143 * op3 & ip0 mustn't be clobbered
144 */
145 movq %rbx, 0(%rsp)
146 movq %rdx, 8(%rsp)
147
148 movq 32(%rsp), %rax /* rax = oend */
149 subq %op3, %rax /* rax = oend - op3 */
150
151 /* r15 = (oend - op3) / 5 */
152 movabsq $-3689348814741910323, %rdx
153 mulq %rdx
154 movq %rdx, %r15
155 shrq $2, %r15
156
157 movq %ip0, %rax /* rax = ip0 */
158 movq 40(%rsp), %rdx /* rdx = ilimit */
159 subq %rdx, %rax /* rax = ip0 - ilimit */
160 movq %rax, %rbx /* rbx = ip0 - ilimit */
161
162 /* rdx = (ip0 - ilimit) / 7 */
163 movabsq $2635249153387078803, %rdx
164 mulq %rdx
165 subq %rdx, %rbx
166 shrq %rbx
167 addq %rbx, %rdx
168 shrq $2, %rdx
169
170 /* r15 = min(%rdx, %r15) */
171 cmpq %rdx, %r15
172 cmova %rdx, %r15
173
174 /* r15 = r15 * 5 */
175 leaq (%r15, %r15, 4), %r15
176
177 /* olimit = op3 + r15 */
178 addq %op3, %olimit
179
180 movq 8(%rsp), %rdx
181 movq 0(%rsp), %rbx
182
183 /* If (op3 + 20 > olimit) */
184 movq %op3, %rax /* rax = op3 */
185 addq $20, %rax /* rax = op3 + 20 */
186 cmpq %rax, %olimit /* op3 + 20 > olimit */
187 jb .L_4X1_exit
188
189 /* If (ip1 < ip0) go to exit */
190 cmpq %ip0, %ip1
191 jb .L_4X1_exit
192
193 /* If (ip2 < ip1) go to exit */
194 cmpq %ip1, %ip2
195 jb .L_4X1_exit
196
197 /* If (ip3 < ip2) go to exit */
198 cmpq %ip2, %ip3
199 jb .L_4X1_exit
200
201/* Reads top 11 bits from bits[n]
202 * Loads dt[bits[n]] into var[n]
203 */
204#define GET_NEXT_DELT(n) \
205 movq $53, %var##n; \
206 shrxq %var##n, %bits##n, %var##n; \
207 movzwl (%dtable,%var##n,2),%vard##n
208
209/* var[n] must contain the DTable entry computed with GET_NEXT_DELT
210 * Moves var[n] to %rax
211 * bits[n] <<= var[n] & 63
212 * op[n][idx] = %rax >> 8
213 * %ah is a way to access bits [8, 16) of %rax
214 */
215#define DECODE_FROM_DELT(n, idx) \
216 movq %var##n, %rax; \
217 shlxq %var##n, %bits##n, %bits##n; \
218 movb %ah, idx(%op##n)
219
220/* Assumes GET_NEXT_DELT has been called.
221 * Calls DECODE_FROM_DELT then GET_NEXT_DELT
222 */
223#define DECODE_AND_GET_NEXT(n, idx) \
224 DECODE_FROM_DELT(n, idx); \
225 GET_NEXT_DELT(n) \
226
227/* // ctz & nbBytes is stored in bits[n]
228 * // nbBits is stored in %rax
229 * ctz = CTZ[bits[n]]
230 * nbBits = ctz & 7
231 * nbBytes = ctz >> 3
232 * op[n] += 5
233 * ip[n] -= nbBytes
234 * // Note: x86-64 is little-endian ==> no bswap
235 * bits[n] = MEM_readST(ip[n]) | 1
236 * bits[n] <<= nbBits
237 */
238#define RELOAD_BITS(n) \
239 bsfq %bits##n, %bits##n; \
240 movq %bits##n, %rax; \
241 andq $7, %rax; \
242 shrq $3, %bits##n; \
243 leaq 5(%op##n), %op##n; \
244 subq %bits##n, %ip##n; \
245 movq (%ip##n), %bits##n; \
246 orq $1, %bits##n; \
247 shlx %rax, %bits##n, %bits##n
248
249 /* Store clobbered variables on the stack */
250 movq %olimit, 24(%rsp)
251 movq %ip1, 0(%rsp)
252 movq %ip2, 8(%rsp)
253 movq %ip3, 16(%rsp)
254
255 /* Call GET_NEXT_DELT for each stream */
256 FOR_EACH_STREAM(GET_NEXT_DELT)
257
258 .p2align 6
259
260.L_4X1_loop_body:
261 /* Decode 5 symbols in each of the 4 streams (20 total)
262 * Must have called GET_NEXT_DELT for each stream
263 */
264 FOR_EACH_STREAM_WITH_INDEX(DECODE_AND_GET_NEXT, 0)
265 FOR_EACH_STREAM_WITH_INDEX(DECODE_AND_GET_NEXT, 1)
266 FOR_EACH_STREAM_WITH_INDEX(DECODE_AND_GET_NEXT, 2)
267 FOR_EACH_STREAM_WITH_INDEX(DECODE_AND_GET_NEXT, 3)
268 FOR_EACH_STREAM_WITH_INDEX(DECODE_FROM_DELT, 4)
269
270 /* Load ip[1,2,3] from stack (var[] aliases them)
271 * ip[] is needed for RELOAD_BITS
272 * Each will be stored back to the stack after RELOAD
273 */
274 movq 0(%rsp), %ip1
275 movq 8(%rsp), %ip2
276 movq 16(%rsp), %ip3
277
278 /* Reload each stream & fetch the next table entry
279 * to prepare for the next iteration
280 */
281 RELOAD_BITS(0)
282 GET_NEXT_DELT(0)
283
284 RELOAD_BITS(1)
285 movq %ip1, 0(%rsp)
286 GET_NEXT_DELT(1)
287
288 RELOAD_BITS(2)
289 movq %ip2, 8(%rsp)
290 GET_NEXT_DELT(2)
291
292 RELOAD_BITS(3)
293 movq %ip3, 16(%rsp)
294 GET_NEXT_DELT(3)
295
296 /* If op3 < olimit: continue the loop */
297 cmp %op3, 24(%rsp)
298 ja .L_4X1_loop_body
299
300 /* Reload ip[1,2,3] from stack */
301 movq 0(%rsp), %ip1
302 movq 8(%rsp), %ip2
303 movq 16(%rsp), %ip3
304
305 /* Re-compute olimit */
306 jmp .L_4X1_compute_olimit
307
308#undef GET_NEXT_DELT
309#undef DECODE_FROM_DELT
310#undef DECODE
311#undef RELOAD_BITS
312.L_4X1_exit:
313 addq $24, %rsp
314
315 /* Restore stack (oend & olimit) */
316 pop %rax /* olimit */
317 pop %rax /* oend */
318 pop %rax /* ilimit */
319 pop %rax /* arg */
320
321 /* Save ip / op / bits */
322 movq %ip0, 0(%rax)
323 movq %ip1, 8(%rax)
324 movq %ip2, 16(%rax)
325 movq %ip3, 24(%rax)
326 movq %op0, 32(%rax)
327 movq %op1, 40(%rax)
328 movq %op2, 48(%rax)
329 movq %op3, 56(%rax)
330 movq %bits0, 64(%rax)
331 movq %bits1, 72(%rax)
332 movq %bits2, 80(%rax)
333 movq %bits3, 88(%rax)
334
335 /* Restore registers */
336 pop %r15
337 pop %r14
338 pop %r13
339 pop %r12
340 pop %r11
341 pop %r10
342 pop %r9
343 pop %r8
344 pop %rdi
345 pop %rsi
346 pop %rbp
347 pop %rdx
348 pop %rcx
349 pop %rbx
350 pop %rax
351 ret
352
353_HUF_decompress4X2_usingDTable_internal_bmi2_asm_loop:
354HUF_decompress4X2_usingDTable_internal_bmi2_asm_loop:
355 /* Save all registers - even if they are callee saved for simplicity. */
356 push %rax
357 push %rbx
358 push %rcx
359 push %rdx
360 push %rbp
361 push %rsi
362 push %rdi
363 push %r8
364 push %r9
365 push %r10
366 push %r11
367 push %r12
368 push %r13
369 push %r14
370 push %r15
371
372 movq %rdi, %rax
373 movq 0(%rax), %ip0
374 movq 8(%rax), %ip1
375 movq 16(%rax), %ip2
376 movq 24(%rax), %ip3
377 movq 32(%rax), %op0
378 movq 40(%rax), %op1
379 movq 48(%rax), %op2
380 movq 56(%rax), %op3
381 movq 64(%rax), %bits0
382 movq 72(%rax), %bits1
383 movq 80(%rax), %bits2
384 movq 88(%rax), %bits3
385 movq 96(%rax), %dtable
386 push %rax /* argument */
387 push %rax /* olimit */
388 push 104(%rax) /* ilimit */
389
390 movq 112(%rax), %rax
391 push %rax /* oend3 */
392
393 movq %op3, %rax
394 push %rax /* oend2 */
395
396 movq %op2, %rax
397 push %rax /* oend1 */
398
399 movq %op1, %rax
400 push %rax /* oend0 */
401
402 /* Scratch space */
403 subq $8, %rsp
404
405.L_4X2_compute_olimit:
406 /* Computes how many iterations we can do safely
407 * %r15, %rax may be clobbered
408 * rdx must be saved
409 * op[1,2,3,4] & ip0 mustn't be clobbered
410 */
411 movq %rdx, 0(%rsp)
412
413 /* We can consume up to 7 input bytes each iteration. */
414 movq %ip0, %rax /* rax = ip0 */
415 movq 40(%rsp), %rdx /* rdx = ilimit */
416 subq %rdx, %rax /* rax = ip0 - ilimit */
417 movq %rax, %r15 /* r15 = ip0 - ilimit */
418
419 /* rdx = rax / 7 */
420 movabsq $2635249153387078803, %rdx
421 mulq %rdx
422 subq %rdx, %r15
423 shrq %r15
424 addq %r15, %rdx
425 shrq $2, %rdx
426
427 /* r15 = (ip0 - ilimit) / 7 */
428 movq %rdx, %r15
429
430 movabsq $-3689348814741910323, %rdx
431 movq 8(%rsp), %rax /* rax = oend0 */
432 subq %op0, %rax /* rax = oend0 - op0 */
433 mulq %rdx
434 shrq $3, %rdx /* rdx = rax / 10 */
435
436 /* r15 = min(%rdx, %r15) */
437 cmpq %rdx, %r15
438 cmova %rdx, %r15
439
440 movabsq $-3689348814741910323, %rdx
441 movq 16(%rsp), %rax /* rax = oend1 */
442 subq %op1, %rax /* rax = oend1 - op1 */
443 mulq %rdx
444 shrq $3, %rdx /* rdx = rax / 10 */
445
446 /* r15 = min(%rdx, %r15) */
447 cmpq %rdx, %r15
448 cmova %rdx, %r15
449
450 movabsq $-3689348814741910323, %rdx
451 movq 24(%rsp), %rax /* rax = oend2 */
452 subq %op2, %rax /* rax = oend2 - op2 */
453 mulq %rdx
454 shrq $3, %rdx /* rdx = rax / 10 */
455
456 /* r15 = min(%rdx, %r15) */
457 cmpq %rdx, %r15
458 cmova %rdx, %r15
459
460 movabsq $-3689348814741910323, %rdx
461 movq 32(%rsp), %rax /* rax = oend3 */
462 subq %op3, %rax /* rax = oend3 - op3 */
463 mulq %rdx
464 shrq $3, %rdx /* rdx = rax / 10 */
465
466 /* r15 = min(%rdx, %r15) */
467 cmpq %rdx, %r15
468 cmova %rdx, %r15
469
470 /* olimit = op3 + 5 * r15 */
471 movq %r15, %rax
472 leaq (%op3, %rax, 4), %olimit
473 addq %rax, %olimit
474
475 movq 0(%rsp), %rdx
476
477 /* If (op3 + 10 > olimit) */
478 movq %op3, %rax /* rax = op3 */
479 addq $10, %rax /* rax = op3 + 10 */
480 cmpq %rax, %olimit /* op3 + 10 > olimit */
481 jb .L_4X2_exit
482
483 /* If (ip1 < ip0) go to exit */
484 cmpq %ip0, %ip1
485 jb .L_4X2_exit
486
487 /* If (ip2 < ip1) go to exit */
488 cmpq %ip1, %ip2
489 jb .L_4X2_exit
490
491 /* If (ip3 < ip2) go to exit */
492 cmpq %ip2, %ip3
493 jb .L_4X2_exit
494
495#define DECODE(n, idx) \
496 movq %bits##n, %rax; \
497 shrq $53, %rax; \
498 movzwl 0(%dtable,%rax,4),%r8d; \
499 movzbl 2(%dtable,%rax,4),%r15d; \
500 movzbl 3(%dtable,%rax,4),%eax; \
501 movw %r8w, (%op##n); \
502 shlxq %r15, %bits##n, %bits##n; \
503 addq %rax, %op##n
504
505#define RELOAD_BITS(n) \
506 bsfq %bits##n, %bits##n; \
507 movq %bits##n, %rax; \
508 shrq $3, %bits##n; \
509 andq $7, %rax; \
510 subq %bits##n, %ip##n; \
511 movq (%ip##n), %bits##n; \
512 orq $1, %bits##n; \
513 shlxq %rax, %bits##n, %bits##n
514
515
516 movq %olimit, 48(%rsp)
517
518 .p2align 6
519
520.L_4X2_loop_body:
521 /* We clobber r8, so store it on the stack */
522 movq %r8, 0(%rsp)
523
524 /* Decode 5 symbols from each of the 4 streams (20 symbols total). */
525 FOR_EACH_STREAM_WITH_INDEX(DECODE, 0)
526 FOR_EACH_STREAM_WITH_INDEX(DECODE, 1)
527 FOR_EACH_STREAM_WITH_INDEX(DECODE, 2)
528 FOR_EACH_STREAM_WITH_INDEX(DECODE, 3)
529 FOR_EACH_STREAM_WITH_INDEX(DECODE, 4)
530
531 /* Reload r8 */
532 movq 0(%rsp), %r8
533
534 FOR_EACH_STREAM(RELOAD_BITS)
535
536 cmp %op3, 48(%rsp)
537 ja .L_4X2_loop_body
538 jmp .L_4X2_compute_olimit
539
540#undef DECODE
541#undef RELOAD_BITS
542.L_4X2_exit:
543 addq $8, %rsp
544 /* Restore stack (oend & olimit) */
545 pop %rax /* oend0 */
546 pop %rax /* oend1 */
547 pop %rax /* oend2 */
548 pop %rax /* oend3 */
549 pop %rax /* ilimit */
550 pop %rax /* olimit */
551 pop %rax /* arg */
552
553 /* Save ip / op / bits */
554 movq %ip0, 0(%rax)
555 movq %ip1, 8(%rax)
556 movq %ip2, 16(%rax)
557 movq %ip3, 24(%rax)
558 movq %op0, 32(%rax)
559 movq %op1, 40(%rax)
560 movq %op2, 48(%rax)
561 movq %op3, 56(%rax)
562 movq %bits0, 64(%rax)
563 movq %bits1, 72(%rax)
564 movq %bits2, 80(%rax)
565 movq %bits3, 88(%rax)
566
567 /* Restore registers */
568 pop %r15
569 pop %r14
570 pop %r13
571 pop %r12
572 pop %r11
573 pop %r10
574 pop %r9
575 pop %r8
576 pop %rdi
577 pop %rsi
578 pop %rbp
579 pop %rdx
580 pop %rcx
581 pop %rbx
582 pop %rax
583 ret
584
585#endif