@@ -555,20 +555,79 @@ void WasmBinaryWriter::writeNames() {
555555 BYN_TRACE (" == writeNames\n " );
556556 auto start = startSection (BinaryConsts::Section::User);
557557 writeInlineString (BinaryConsts::UserSections::Name);
558- auto substart =
559- startSubsection (BinaryConsts::UserSections::Subsection::NameFunction);
560- o << U32LEB (indexes.functionIndexes .size ());
561- Index emitted = 0 ;
562- auto add = [&](Function* curr) {
563- o << U32LEB (emitted);
564- writeEscapedName (curr->name .str );
565- emitted++;
566- };
567- ModuleUtils::iterImportedFunctions (*wasm, add);
568- ModuleUtils::iterDefinedFunctions (*wasm, add);
569- assert (emitted == indexes.functionIndexes .size ());
570- finishSubsection (substart);
571- /* TODO: locals */
558+
559+ // module name
560+ if (wasm->name .is ()) {
561+ auto substart =
562+ startSubsection (BinaryConsts::UserSections::Subsection::NameModule);
563+ writeEscapedName (wasm->name .str );
564+ finishSubsection (substart);
565+ }
566+
567+ // function names
568+ {
569+ auto substart =
570+ startSubsection (BinaryConsts::UserSections::Subsection::NameFunction);
571+ o << U32LEB (indexes.functionIndexes .size ());
572+ Index emitted = 0 ;
573+ auto add = [&](Function* curr) {
574+ o << U32LEB (emitted);
575+ writeEscapedName (curr->name .str );
576+ emitted++;
577+ };
578+ ModuleUtils::iterImportedFunctions (*wasm, add);
579+ ModuleUtils::iterDefinedFunctions (*wasm, add);
580+ assert (emitted == indexes.functionIndexes .size ());
581+ finishSubsection (substart);
582+ }
583+
584+ // local names
585+ {
586+ // Find all functions with at least one local name and only emit the
587+ // subsection if there is at least one.
588+ std::vector<std::pair<Index, Function*>> functionsWithLocalNames;
589+ Index checked = 0 ;
590+ auto check = [&](Function* curr) {
591+ auto numLocals = curr->getNumLocals ();
592+ for (Index i = 0 ; i < numLocals; ++i) {
593+ if (curr->hasLocalName (i)) {
594+ functionsWithLocalNames.push_back ({checked, curr});
595+ break ;
596+ }
597+ }
598+ checked++;
599+ };
600+ ModuleUtils::iterImportedFunctions (*wasm, check);
601+ ModuleUtils::iterDefinedFunctions (*wasm, check);
602+ assert (checked == indexes.functionIndexes .size ());
603+ if (functionsWithLocalNames.size () > 0 ) {
604+ // Otherwise emit those functions but only include locals with a name.
605+ auto substart =
606+ startSubsection (BinaryConsts::UserSections::Subsection::NameLocal);
607+ o << U32LEB (functionsWithLocalNames.size ());
608+ Index emitted = 0 ;
609+ for (auto & indexedFunc : functionsWithLocalNames) {
610+ std::vector<std::pair<Index, Name>> localsWithNames;
611+ auto numLocals = indexedFunc.second ->getNumLocals ();
612+ for (Index i = 0 ; i < numLocals; ++i) {
613+ if (indexedFunc.second ->hasLocalName (i)) {
614+ localsWithNames.push_back ({i, indexedFunc.second ->getLocalName (i)});
615+ }
616+ }
617+ assert (localsWithNames.size ());
618+ o << U32LEB (indexedFunc.first );
619+ o << U32LEB (localsWithNames.size ());
620+ for (auto & indexedLocal : localsWithNames) {
621+ o << U32LEB (indexedLocal.first );
622+ writeEscapedName (indexedLocal.second .str );
623+ }
624+ emitted++;
625+ }
626+ assert (emitted == functionsWithLocalNames.size ());
627+ finishSubsection (substart);
628+ }
629+ }
630+
572631 finishSection (start);
573632}
574633
@@ -2126,33 +2185,72 @@ void WasmBinaryBuilder::readNames(size_t payloadLen) {
21262185 auto nameType = getU32LEB ();
21272186 auto subsectionSize = getU32LEB ();
21282187 auto subsectionPos = pos;
2129- if (nameType != BinaryConsts::UserSections::Subsection::NameFunction) {
2130- // TODO: locals
2131- std::cerr << " warning: unknown name subsection at " << pos << std::endl;
2132- pos = subsectionPos + subsectionSize;
2133- continue ;
2134- }
2135- auto num = getU32LEB ();
2136- std::set<Name> usedNames;
2137- for (size_t i = 0 ; i < num; i++) {
2138- auto index = getU32LEB ();
2139- auto rawName = getInlineString ();
2140- rawName = escape (rawName);
2141- auto name = rawName;
2142- // De-duplicate names by appending .1, .2, etc.
2143- for (int i = 1 ; !usedNames.insert (name).second ; ++i) {
2144- name = rawName.str + std::string (" ." ) + std::to_string (i);
2188+ if (nameType == BinaryConsts::UserSections::Subsection::NameModule) {
2189+ wasm.name = getInlineString ();
2190+ } else if (nameType ==
2191+ BinaryConsts::UserSections::Subsection::NameFunction) {
2192+ auto num = getU32LEB ();
2193+ std::set<Name> usedNames;
2194+ for (size_t i = 0 ; i < num; i++) {
2195+ auto index = getU32LEB ();
2196+ auto rawName = getInlineString ();
2197+ rawName = escape (rawName);
2198+ auto name = rawName;
2199+ // De-duplicate names by appending .1, .2, etc.
2200+ for (int i = 1 ; !usedNames.insert (name).second ; ++i) {
2201+ name = rawName.str + std::string (" ." ) + std::to_string (i);
2202+ }
2203+ // note: we silently ignore errors here, as name section errors
2204+ // are not fatal. should we warn?
2205+ auto numFunctionImports = functionImports.size ();
2206+ if (index < numFunctionImports) {
2207+ functionImports[index]->name = name;
2208+ } else if (index - numFunctionImports < functions.size ()) {
2209+ functions[index - numFunctionImports]->name = name;
2210+ } else {
2211+ std::cerr << " warning: function index out of bounds in name section, "
2212+ " function subsection: "
2213+ << std::string (name.str ) << " at index "
2214+ << std::to_string (index) << std::endl;
2215+ }
21452216 }
2146- // note: we silently ignore errors here, as name section errors
2147- // are not fatal. should we warn?
2217+ } else if (nameType == BinaryConsts::UserSections::Subsection::NameLocal) {
2218+ auto numFuncs = getU32LEB ();
21482219 auto numFunctionImports = functionImports.size ();
2149- if (index < numFunctionImports) {
2150- functionImports[index]->name = name;
2151- } else if (index - numFunctionImports < functions.size ()) {
2152- functions[index - numFunctionImports]->name = name;
2153- } else {
2154- throwError (" index out of bounds: " + std::string (name.str ));
2220+ for (size_t i = 0 ; i < numFuncs; i++) {
2221+ auto funcIndex = getU32LEB ();
2222+ Function* func = nullptr ;
2223+ if (funcIndex < numFunctionImports) {
2224+ func = functionImports[funcIndex];
2225+ } else if (funcIndex - numFunctionImports < functions.size ()) {
2226+ func = functions[funcIndex - numFunctionImports];
2227+ } else {
2228+ std::cerr
2229+ << " warning: function index out of bounds in name section, local "
2230+ " subsection: "
2231+ << std::to_string (funcIndex) << std::endl;
2232+ }
2233+ auto numLocals = getU32LEB ();
2234+ for (size_t j = 0 ; j < numLocals; j++) {
2235+ auto localIndex = getU32LEB ();
2236+ auto localName = getInlineString ();
2237+ if (!func) {
2238+ continue ; // read and discard in case of prior error
2239+ }
2240+ if (localIndex < func->getNumLocals ()) {
2241+ func->localNames [localIndex] = localName;
2242+ } else {
2243+ std::cerr << " warning: local index out of bounds in name "
2244+ " section, local subsection: "
2245+ << std::string (localName.str ) << " at index "
2246+ << std::to_string (localIndex) << " in function "
2247+ << std::string (func->name .str ) << std::endl;
2248+ }
2249+ }
21552250 }
2251+ } else {
2252+ std::cerr << " warning: unknown name subsection at " << pos << std::endl;
2253+ pos = subsectionPos + subsectionSize;
21562254 }
21572255 if (pos != subsectionPos + subsectionSize) {
21582256 throwError (" bad names subsection position change" );
0 commit comments