diff --git a/src/generate-names.cc b/src/generate-names.cc index f61b4ff58..c562a668c 100644 --- a/src/generate-names.cc +++ b/src/generate-names.cc @@ -179,6 +179,12 @@ void NameGenerator::MaybeUseAndBindName(BindingHash* bindings, Index index, std::string* str) { if (!HasName(*str)) { + if (!HasName(name)) { + // An empty import or export name would produce a bare "$", which is not + // a valid identifier. Leave the name unset; the index-based pass that + // runs afterwards will give it a usable one. + return; + } unsigned disambiguator = 0; while (true) { GenerateName(name, kInvalidIndex, disambiguator, str); diff --git a/test/roundtrip/generate-empty-export-name.txt b/test/roundtrip/generate-empty-export-name.txt new file mode 100644 index 000000000..ede62d7ff --- /dev/null +++ b/test/roundtrip/generate-empty-export-name.txt @@ -0,0 +1,22 @@ +;;; TOOL: run-roundtrip +;;; ARGS: --stdout --generate-names + +(module + ;; With no name section the generated names come from the exports. An empty + ;; export name cannot be used as an identifier, since it would produce a bare + ;; "$", so it has to be skipped: this func has no other export to take a name + ;; from and falls back to an index-based name. + (func $f) + (export "" (func $f)) + + (func $g) + (export "named" (func $g)) +) +(;; STDOUT ;;; +(module + (type $t0 (func)) + (func $f0 (type $t0)) + (func $named (type $t0)) + (export "" (func $f0)) + (export "named" (func $named))) +;;; STDOUT ;;) diff --git a/test/wasm2c/export-names.txt b/test/wasm2c/export-names.txt index 775054988..dfce091ab 100644 --- a/test/wasm2c/export-names.txt +++ b/test/wasm2c/export-names.txt @@ -926,7 +926,7 @@ DEFINE_TABLE_FILL(externref) wasm_rt_tailcallee_t* next) #endif -static void w2c_test__0(w2c_test*); +static void w2c_test_0x2A0x2F_0(w2c_test*); FUNC_TYPE_T(w2c_test_t0) = "\x36\xa9\xe7\xf1\xc9\x5b\x82\xff\xb9\x97\x43\xe0\xc5\xc4\xce\x95\xd8\x3c\x9a\x43\x0a\xac\x59\xf8\x4e\xf3\xcb\xfa\xb6\x14\x50\x68"; @@ -941,7 +941,7 @@ void w2c_test_(w2c_test* instance) { #endif wasm_rt_segue_write_base((*instance->w2c_0x5Cmodule_import0x200x2A0x2F).data); #endif - w2c_test__0(instance); + w2c_test_0x2A0x2F_0(instance); #if WASM_RT_USE_SEGUE_FOR_THIS_MODULE && !WASM_RT_SEGUE_FREE_SEGMENT wasm_rt_segue_write_base(segue_saved_base); #endif @@ -955,7 +955,7 @@ void w2c_test_0x2A0x2F(w2c_test* instance) { #endif wasm_rt_segue_write_base((*instance->w2c_0x5Cmodule_import0x200x2A0x2F).data); #endif - w2c_test__0(instance); + w2c_test_0x2A0x2F_0(instance); #if WASM_RT_USE_SEGUE_FOR_THIS_MODULE && !WASM_RT_SEGUE_FREE_SEGMENT wasm_rt_segue_write_base(segue_saved_base); #endif @@ -969,7 +969,7 @@ void w2c_test_0x3F0x3F0x2F(w2c_test* instance) { #endif wasm_rt_segue_write_base((*instance->w2c_0x5Cmodule_import0x200x2A0x2F).data); #endif - w2c_test__0(instance); + w2c_test_0x2A0x2F_0(instance); #if WASM_RT_USE_SEGUE_FOR_THIS_MODULE && !WASM_RT_SEGUE_FREE_SEGMENT wasm_rt_segue_write_base(segue_saved_base); #endif @@ -983,7 +983,7 @@ void w2c_test_0x0A(w2c_test* instance) { #endif wasm_rt_segue_write_base((*instance->w2c_0x5Cmodule_import0x200x2A0x2F).data); #endif - w2c_test__0(instance); + w2c_test_0x2A0x2F_0(instance); #if WASM_RT_USE_SEGUE_FOR_THIS_MODULE && !WASM_RT_SEGUE_FREE_SEGMENT wasm_rt_segue_write_base(segue_saved_base); #endif @@ -997,7 +997,7 @@ void w2c_test_0xE20x9D0xA40xEF0xB80x8F(w2c_test* instance) { #endif wasm_rt_segue_write_base((*instance->w2c_0x5Cmodule_import0x200x2A0x2F).data); #endif - w2c_test__0(instance); + w2c_test_0x2A0x2F_0(instance); #if WASM_RT_USE_SEGUE_FOR_THIS_MODULE && !WASM_RT_SEGUE_FREE_SEGMENT wasm_rt_segue_write_base(segue_saved_base); #endif @@ -1045,7 +1045,7 @@ wasm_rt_func_type_t wasm2c_test_get_func_type(uint32_t param_count, uint32_t res return NULL; } -void w2c_test__0(w2c_test* instance) { +void w2c_test_0x2A0x2F_0(w2c_test* instance) { FUNC_PROLOGUE; uint8_t* const wasm_rt_local_memory_base = (instance->w2c_0x5Cmodule_import0x200x2A0x2F)->data; uint64_t wasm_rt_local_memory_size = (instance->w2c_0x5Cmodule_import0x200x2A0x2F)->size;