Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 0 additions & 55 deletions src/ir/names.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,59 +70,4 @@ std::string MinifiedNameGenerator::getName() {
return name;
}

static bool isIdChar(char ch) {
return (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z') ||
(ch >= 'a' && ch <= 'z') || ch == '!' || ch == '#' || ch == '$' ||
ch == '%' || ch == '&' || ch == '\'' || ch == '*' || ch == '+' ||
ch == '-' || ch == '.' || ch == '/' || ch == ':' || ch == '<' ||
ch == '=' || ch == '>' || ch == '?' || ch == '@' || ch == '^' ||
ch == '_' || ch == '`' || ch == '|' || ch == '~';
}

static char formatNibble(int nibble) {
return nibble < 10 ? '0' + nibble : 'a' - 10 + nibble;
}

Name escape(Name name) {
bool allIdChars = true;
for (char c : name.view()) {
if (!(allIdChars = isIdChar(c))) {
break;
}
}
if (allIdChars) {
return name;
}
// encode name, if at least one non-idchar (per WebAssembly spec) was found
std::string escaped;
for (char c : name.view()) {
if (isIdChar(c)) {
escaped.push_back(c);
continue;
}
// replace non-idchar with `\xx` escape
escaped.push_back('\\');
escaped.push_back(formatNibble((unsigned char)c >> 4));
escaped.push_back(formatNibble((unsigned char)c & 15));
}
return escaped;
}

std::string unescape(Name name) {
std::string output;
std::string_view input = name.view();
for (size_t i = 0; i < input.length(); i++) {
if ((input[i] == '\\') && (i + 2 < input.length()) &&
isxdigit(input[i + 1]) && isxdigit(input[i + 2])) {
std::string byte = std::string(input.substr(i + 1, 2));
i += 2;
char chr = (char)(int)strtol(byte.c_str(), nullptr, 16);
output.push_back(chr);
} else {
output.push_back(input[i]);
}
}
return output;
}

} // namespace wasm::Names
7 changes: 0 additions & 7 deletions src/ir/names.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,13 +138,6 @@ class MinifiedNameGenerator {
std::string getName();
};

// Escapes a string into a valid WebAssembly identifier by converting invalid
// characters to \xx hex sequences.
Name escape(Name name);
// Unescapes a WebAssembly identifier back into its original human-readable
// string.
std::string unescape(Name name);

} // namespace wasm::Names

#endif // wasm_ir_names_h
19 changes: 8 additions & 11 deletions src/passes/Asyncify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -475,32 +475,29 @@ class PatternMatcher {
std::set<Name> names;
std::set<std::string> patterns;
std::set<std::string> patternsMatched;
std::map<std::string, std::string> unescaped;

PatternMatcher(std::string designation,
Module& module,
const String::Split& list)
: designation(designation) {
// The lists contain human-readable strings. Turn them into the
// internal escaped names for later comparisons
// internal names for later comparisons.
for (auto& name : list) {
auto escaped = Names::escape(name);
unescaped[escaped.toString()] = name;
if (name.find('*') != std::string::npos) {
patterns.insert(escaped.toString());
patterns.insert(name);
} else {
auto* func = module.getFunctionOrNull(escaped);
auto* func = module.getFunctionOrNull(name);
if (!func) {
std::cerr << "warning: Asyncify " << designation
<< "list contained a non-existing function name: " << name
<< " (" << escaped << ")\n";
<< "list contained a non-existing function name: '" << name
<< "'\n";
} else if (func->imported()) {
Fatal() << "Asyncify " << designation
<< "list contained an imported function name (use the import "
"list for imports): "
<< name << '\n';
}
names.insert(escaped.str);
names.insert(name);
}
}
}
Expand All @@ -523,8 +520,8 @@ class PatternMatcher {
for (auto& pattern : patterns) {
if (!patternsMatched.contains(pattern)) {
std::cerr << "warning: Asyncify " << designation
<< "list contained a non-matching pattern: "
<< unescaped[pattern] << " (" << pattern << ")\n";
<< "list contained a non-matching pattern: '" << pattern
<< "'\n";
}
}
}
Expand Down
6 changes: 0 additions & 6 deletions src/tools/wasm-split/split-options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -365,12 +365,6 @@ WasmSplitOptions::WasmSplitOptions()
{Mode::Instrument, Mode::MergeProfiles, Mode::MultiSplit},
Options::Arguments::One,
[&](Options* o, const std::string& argument) { output = argument; })
.add("--unescape",
"-u",
"Un-escape function names (in print-profile output)",
WasmSplitOption,
Options::Arguments::Zero,
[&](Options* o, const std::string& argument) { unescape = true; })
.add("--verbose",
"-v",
"Verbose output mode. Prints the functions that will be kept "
Expand Down
1 change: 0 additions & 1 deletion src/tools/wasm-split/split-options.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ struct WasmSplitOptions : ToolOptions {
StorageKind storageKind = StorageKind::InGlobals;

bool usePlaceholders = true;
bool unescape = false;
bool verbose = false;
bool emitBinary = true;
bool symbolMap = false;
Expand Down
6 changes: 2 additions & 4 deletions src/tools/wasm-split/wasm-split.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,7 @@ void multiSplitModule(const WasmSplitOptions& options) {
}
continue;
}
Name name = Names::escape(line);
Name name = line;
if (newSection) {
if (name.endsWith(":")) {
name = name.substr(0, name.size() - 1);
Expand Down Expand Up @@ -586,9 +586,7 @@ void printReadableProfile(const WasmSplitOptions& options) {

auto printFnSet = [&](auto funcs, std::string prefix) {
for (auto it = funcs.begin(); it != funcs.end(); ++it) {
std::cout << prefix << " "
<< (options.unescape ? Names::unescape(*it) : it->toString())
<< std::endl;
std::cout << prefix << " " << it->toString() << std::endl;
}
};

Expand Down
1 change: 0 additions & 1 deletion src/wasm-binary.h
Original file line number Diff line number Diff line change
Expand Up @@ -1489,7 +1489,6 @@ class WasmBinaryWriter {

// helpers
void writeInlineString(std::string_view name);
void writeEscapedName(std::string_view name);
void writeInlineBuffer(const char* data, size_t size);
void writeData(const char* data, size_t size);

Expand Down
69 changes: 18 additions & 51 deletions src/wasm/wasm-binary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -917,7 +917,7 @@ void WasmBinaryWriter::writeNames() {
if (emitModuleName && wasm->name.is()) {
auto substart =
startSubsection(BinaryConsts::CustomSections::Subsection::NameModule);
writeEscapedName(wasm->name.view());
writeInlineString(wasm->name.view());
finishSubsection(substart);
}

Expand Down Expand Up @@ -946,7 +946,7 @@ void WasmBinaryWriter::writeNames() {
o << U32LEB(functionsWithNames.size());
for (auto& [index, global] : functionsWithNames) {
o << U32LEB(index);
writeEscapedName(global->name.view());
writeInlineString(global->name.view());
}
finishSubsection(substart);
}
Expand Down Expand Up @@ -1006,7 +1006,7 @@ void WasmBinaryWriter::writeNames() {
o << U32LEB(localsWithNames.size());
for (auto& [indexInBinary, name] : localsWithNames) {
o << U32LEB(indexInBinary);
writeEscapedName(name.view());
writeInlineString(name.view());
}
emitted++;
}
Expand All @@ -1029,7 +1029,7 @@ void WasmBinaryWriter::writeNames() {
o << U32LEB(namedTypes.size());
for (auto type : namedTypes) {
o << U32LEB(indexedTypes.indices[type]);
writeEscapedName(wasm->typeNames[type].name.view());
writeInlineString(wasm->typeNames[type].name.view());
}
finishSubsection(substart);
}
Expand All @@ -1056,7 +1056,7 @@ void WasmBinaryWriter::writeNames() {

for (auto& [index, table] : tablesWithNames) {
o << U32LEB(index);
writeEscapedName(table->name.view());
writeInlineString(table->name.view());
}

finishSubsection(substart);
Expand All @@ -1082,7 +1082,7 @@ void WasmBinaryWriter::writeNames() {
o << U32LEB(memoriesWithNames.size());
for (auto& [index, memory] : memoriesWithNames) {
o << U32LEB(index);
writeEscapedName(memory->name.view());
writeInlineString(memory->name.view());
}
finishSubsection(substart);
}
Expand All @@ -1107,7 +1107,7 @@ void WasmBinaryWriter::writeNames() {
o << U32LEB(globalsWithNames.size());
for (auto& [index, global] : globalsWithNames) {
o << U32LEB(index);
writeEscapedName(global->name.view());
writeInlineString(global->name.view());
}
finishSubsection(substart);
}
Expand All @@ -1132,7 +1132,7 @@ void WasmBinaryWriter::writeNames() {

for (auto& [index, elem] : elemsWithNames) {
o << U32LEB(index);
writeEscapedName(elem->name.view());
writeInlineString(elem->name.view());
}

finishSubsection(substart);
Expand All @@ -1156,7 +1156,7 @@ void WasmBinaryWriter::writeNames() {
auto& seg = wasm->dataSegments[i];
if (seg->hasExplicitName) {
o << U32LEB(i);
writeEscapedName(seg->name.view());
writeInlineString(seg->name.view());
}
}
finishSubsection(substart);
Expand Down Expand Up @@ -1187,7 +1187,7 @@ void WasmBinaryWriter::writeNames() {
o << U32LEB(fieldNames.size());
for (auto& [index, name] : fieldNames) {
o << U32LEB(index);
writeEscapedName(name.view());
writeInlineString(name.view());
}
}
finishSubsection(substart);
Expand All @@ -1213,7 +1213,7 @@ void WasmBinaryWriter::writeNames() {
o << U32LEB(tagsWithNames.size());
for (auto& [index, tag] : tagsWithNames) {
o << U32LEB(index);
writeEscapedName(tag->name.view());
writeInlineString(tag->name.view());
}
finishSubsection(substart);
}
Expand Down Expand Up @@ -1846,37 +1846,6 @@ void WasmBinaryWriter::writeInlineString(std::string_view name) {
o.writeInlineString(name);
}

static bool isHexDigit(char ch) {
return (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') ||
(ch >= 'A' && ch <= 'F');
}

static int decodeHexNibble(char ch) {
return ch <= '9' ? ch & 15 : (ch & 15) + 9;
}

void WasmBinaryWriter::writeEscapedName(std::string_view name) {
if (name.find('\\') == std::string_view::npos) {
writeInlineString(name);
return;
}
// decode escaped by escapeName (see below) function names
std::string unescaped;
for (size_t i = 0; i < name.size();) {
char ch = name[i++];
// support only `\xx` escapes; ignore invalid or unsupported escapes
if (ch != '\\' || i + 1 >= name.size() || !isHexDigit(name[i]) ||
!isHexDigit(name[i + 1])) {
unescaped.push_back(ch);
continue;
}
unescaped.push_back(
char((decodeHexNibble(name[i]) << 4) | decodeHexNibble(name[i + 1])));
i += 2;
}
writeInlineString({unescaped.data(), unescaped.size()});
}
Comment on lines -1858 to -1878

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The binary writer was further escaping names when writing them back to the names section.

Isn't this unescaping names despite the name tells the opposite? Anyway, if the IR has unescaped names now and the name section should have the same, removing this looks correct.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yes, you're right. I'll update the description.


void WasmBinaryWriter::writeInlineBuffer(const char* data, size_t size) {
o << U32LEB(size);
writeData(data, size);
Expand Down Expand Up @@ -5310,21 +5279,19 @@ void WasmBinaryReader::readTags() {
namespace {

// Performs necessary processing of names from the name section before using
// them. Specifically it escapes and deduplicates them.
// them. Specifically it deduplicates them.
class NameProcessor {
public:
// Returns a unique, escaped name. Notes that name for the items to follow to
// Returns a unique name. Notes that name for the items to follow to
// keep them unique as well.
Name process(Name name) { return deduplicate(Names::escape(name)); }

private:
std::unordered_set<Name> usedNames;

Name deduplicate(Name base) {
auto name = Names::getValidNameGivenExisting(base, usedNames);
Name process(Name name) {
name = Names::getValidNameGivenExisting(name, usedNames);
usedNames.insert(name);
return name;
}

private:
std::unordered_set<Name> usedNames;
};

} // anonymous namespace
Expand Down
4 changes: 2 additions & 2 deletions test/binaryen.js/debug-names.js.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
(memory $lo 0 0)
(table $wor 0 0 funcref)
(func $of (param $js i32)
(local $!#$%&'*+-./:<=>?@\5c^_`|~ f64)
(local $!#$%&'*+-./:<=>?@\^_`|~ f64)
)
)

Expand All @@ -37,7 +37,7 @@
(memory $lo 0 0)
(table $wor 0 0 funcref)
(func $of (param $js i32)
(local $!#$%&'*+-./:<=>?@\5c^_`|~ f64)
(local $!#$%&'*+-./:<=>?@\^_`|~ f64)
)
)

4 changes: 2 additions & 2 deletions test/complexBinaryNames.wasm.fromBinary
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
(module
(type $0 (func))
(export "$zoo (.bar)" (func $1))
(func $foo\20\28.bar\29
(func $"foo (.bar)"
(nop)
)
(func $1
(call $foo\20\28.bar\29)
(call $"foo (.bar)")
)
)

6 changes: 3 additions & 3 deletions test/finalize/shared_add_to_table.wasm.out
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@
(import "GOT.func" "_Z14waka_func_minei" (global $gimport$4 (mut i32)))
(import "GOT.mem" "waka_mine" (global $gimport$5 (mut i32)))
(import "GOT.mem" "waka_others" (global $gimport$6 (mut i32)))
(import "env" "_Z16waka_func_theirsi" (func $waka_func_theirs\28int\29 (param i32) (result i32)))
(import "env" "_Z16waka_func_theirsi" (func $"waka_func_theirs(int)" (param i32) (result i32)))
(global $global$0 i32 (i32.const 0))
(global $global$1 i32 (i32.const 0))
(data $0 (global.get $gimport$1) "*\00\00\00")
(export "__wasm_call_ctors" (func $__wasm_call_ctors))
(export "__wasm_apply_relocs" (func $__wasm_apply_relocs))
(export "_Z14waka_func_minei" (func $waka_func_mine\28int\29))
(export "_Z14waka_func_minei" (func $"waka_func_mine(int)"))
(export "__original_main" (func $__original_main))
(export "waka_mine" (global $global$0))
(export "main" (func $main))
Expand All @@ -28,7 +28,7 @@
)
(func $__wasm_apply_relocs
)
(func $waka_func_mine\28int\29 (param $0 i32) (result i32)
(func $"waka_func_mine(int)" (param $0 i32) (result i32)
(i32.add
(local.get $0)
(i32.const 1)
Expand Down
Loading
Loading