@@ -411,7 +411,6 @@ enum ASTNodes {
411411 SetLocal = 0x15 ,
412412 CallFunction = 0x16 ,
413413 CallIndirect = 0x17 ,
414- CallImport = 0x18 ,
415414 TeeLocal = 0x19 ,
416415 GetGlobal = 0x1a ,
417416 SetGlobal = 0x1b ,
@@ -727,27 +726,21 @@ class WasmBinaryWriter : public Visitor<WasmBinaryWriter, void> {
727726 }
728727 finishSection (start);
729728 }
730-
731- std::map<Name, uint32_t > mappedImports; // name of the Import => index
732- uint32_t getImportIndex (Name name) {
733- if (!mappedImports.size ()) {
734- // Create name => index mapping.
735- for (size_t i = 0 ; i < wasm->imports .size (); i++) {
736- assert (mappedImports.count (wasm->imports [i]->name ) == 0 );
737- mappedImports[wasm->imports [i]->name ] = i;
738- }
739- }
740- assert (mappedImports.count (name));
741- return mappedImports[name];
742- }
743729
744- std::map<Name, uint32_t > mappedFunctions; // name of the Function => index
730+ std::map<Name, Index > mappedFunctions; // name of the Function => index. first imports, then internals
745731 uint32_t getFunctionIndex (Name name) {
746732 if (!mappedFunctions.size ()) {
747733 // Create name => index mapping.
734+ for (auto & import : wasm->imports ) {
735+ if (import ->kind != Import::Function) continue ;
736+ assert (mappedFunctions.count (import ->name ) == 0 );
737+ auto index = mappedFunctions.size ();
738+ mappedFunctions[import ->name ] = index;
739+ }
748740 for (size_t i = 0 ; i < wasm->functions .size (); i++) {
749741 assert (mappedFunctions.count (wasm->functions [i]->name ) == 0 );
750- mappedFunctions[wasm->functions [i]->name ] = i;
742+ auto index = mappedFunctions.size ();
743+ mappedFunctions[wasm->functions [i]->name ] = index;
751744 }
752745 }
753746 assert (mappedFunctions.count (name));
@@ -957,7 +950,7 @@ class WasmBinaryWriter : public Visitor<WasmBinaryWriter, void> {
957950 for (auto * operand : curr->operands ) {
958951 recurse (operand);
959952 }
960- o << int8_t (BinaryConsts::CallImport ) << U32LEB (curr->operands .size ()) << U32LEB (getImportIndex (curr->target ));
953+ o << int8_t (BinaryConsts::CallFunction ) << U32LEB (curr->operands .size ()) << U32LEB (getFunctionIndex (curr->target ));
961954 }
962955 void visitCallIndirect (CallIndirect *curr) {
963956 if (debug) std::cerr << " zz node: CallIndirect" << std::endl;
@@ -1501,6 +1494,20 @@ class WasmBinaryBuilder {
15011494 }
15021495 }
15031496
1497+ std::vector<Name> functionImportIndexes; // index in function index space => name of function import
1498+
1499+ // gets a name in the combined function import+defined function space
1500+ Name getFunctionIndexName (Index i) {
1501+ if (i < functionImportIndexes.size ()) {
1502+ auto * import = wasm.getImport (functionImportIndexes[i]);
1503+ assert (import ->kind == Import::Function);
1504+ return import ->name ;
1505+ } else {
1506+ i -= functionImportIndexes.size ();
1507+ return wasm.functions .at (i)->name ;
1508+ }
1509+ }
1510+
15041511 void readImports () {
15051512 if (debug) std::cerr << " == readImports" << std::endl;
15061513 size_t num = getU32LEB ();
@@ -1511,16 +1518,17 @@ class WasmBinaryBuilder {
15111518 curr->name = Name (std::string (" import$" ) + std::to_string (i));
15121519 curr->kind = (Import::Kind)getU32LEB ();
15131520 switch (curr->kind ) {
1514- case Export ::Function: {
1521+ case Import ::Function: {
15151522 auto index = getU32LEB ();
15161523 assert (index < wasm.functionTypes .size ());
15171524 curr->functionType = wasm.getFunctionType (index);
15181525 assert (curr->functionType ->name .is ());
1526+ functionImportIndexes.push_back (curr->name );
15191527 break ;
15201528 }
1521- case Export ::Table: break ;
1522- case Export ::Memory: break ;
1523- case Export ::Global: curr->globalType = getWasmType (); break ;
1529+ case Import ::Table: break ;
1530+ case Import ::Memory: break ;
1531+ case Import ::Global: curr->globalType = getWasmType (); break ;
15241532 default : WASM_UNREACHABLE ();
15251533 }
15261534 curr->module = getInlineString ();
@@ -1529,7 +1537,7 @@ class WasmBinaryBuilder {
15291537 }
15301538 }
15311539
1532- std::vector<FunctionType*> functionTypes;
1540+ std::vector<FunctionType*> functionTypes; // types of defined functions
15331541
15341542 void readFunctionSignatures () {
15351543 if (debug) std::cerr << " == readFunctionSignatures" << std::endl;
@@ -1551,7 +1559,7 @@ class WasmBinaryBuilder {
15511559 // We read functions before we know their names, so we need to backpatch the names later
15521560
15531561 std::vector<Function*> functions; // we store functions here before wasm.addFunction after we know their names
1554- std::map<size_t , std::vector<Call*>> functionCalls; // at index i we have all calls to i
1562+ std::map<Index , std::vector<Call*>> functionCalls; // at index i we have all calls to the defined function i
15551563 Function* currFunction = nullptr ;
15561564 size_t endOfFunction;
15571565
@@ -1611,7 +1619,7 @@ class WasmBinaryBuilder {
16111619 }
16121620 }
16131621
1614- std::map<Export*, size_t > exportIndexes;
1622+ std::map<Export*, Index > exportIndexes;
16151623
16161624 void readExports () {
16171625 if (debug) std::cerr << " == readExports" << std::endl;
@@ -1705,7 +1713,10 @@ class WasmBinaryBuilder {
17051713 for (auto & iter : exportIndexes) {
17061714 Export* curr = iter.first ;
17071715 switch (curr->kind ) {
1708- case Export::Function: curr->value = wasm.functions [iter.second ]->name ; break ;
1716+ case Export::Function: {
1717+ curr->value = getFunctionIndexName (iter.second );
1718+ break ;
1719+ }
17091720 case Export::Table: curr->value = Name::fromInt (0 ); break ;
17101721 case Export::Memory: curr->value = Name::fromInt (0 ); break ;
17111722 case Export::Global: curr->value = getGlobalName (iter.second ); break ;
@@ -1726,7 +1737,7 @@ class WasmBinaryBuilder {
17261737 auto i = pair.first ;
17271738 auto & indexes = pair.second ;
17281739 for (auto j : indexes) {
1729- wasm.table .segments [i].data .push_back (wasm. functions [j]-> name );
1740+ wasm.table .segments [i].data .push_back (getFunctionIndexName (j) );
17301741 }
17311742 }
17321743 }
@@ -1795,8 +1806,7 @@ class WasmBinaryBuilder {
17951806 case BinaryConsts::Br:
17961807 case BinaryConsts::BrIf: visitBreak ((curr = allocator.alloc <Break>())->cast <Break>(), code); break ; // code distinguishes br from br_if
17971808 case BinaryConsts::TableSwitch: visitSwitch ((curr = allocator.alloc <Switch>())->cast <Switch>()); break ;
1798- case BinaryConsts::CallFunction: visitCall ((curr = allocator.alloc <Call>())->cast <Call>()); break ;
1799- case BinaryConsts::CallImport: visitCallImport ((curr = allocator.alloc <CallImport>())->cast <CallImport>()); break ;
1809+ case BinaryConsts::CallFunction: curr = visitCall (); break ; // we don't know if it's a call or call_import yet
18001810 case BinaryConsts::CallIndirect: visitCallIndirect ((curr = allocator.alloc <CallIndirect>())->cast <CallIndirect>()); break ;
18011811 case BinaryConsts::GetLocal: visitGetLocal ((curr = allocator.alloc <GetLocal>())->cast <GetLocal>()); break ;
18021812 case BinaryConsts::TeeLocal:
@@ -1938,38 +1948,45 @@ class WasmBinaryBuilder {
19381948 }
19391949 curr->default_ = getBreakName (getInt32 ());
19401950 }
1941- void visitCall (Call *curr) {
1942- if (debug) std::cerr << " zz node: Call" << std::endl;
1943- auto arity = getU32LEB ();
1944- WASM_UNUSED (arity);
1945- auto index = getU32LEB ();
1946- assert (index < functionTypes.size ());
1947- auto type = functionTypes[index];
1951+
1952+ template <typename T>
1953+ void fillCall (T* call, FunctionType* type, Index arity) {
1954+ assert (type);
19481955 auto num = type->params .size ();
19491956 assert (num == arity);
1950- curr ->operands .resize (num);
1957+ call ->operands .resize (num);
19511958 for (size_t i = 0 ; i < num; i++) {
1952- curr ->operands [num - i - 1 ] = popExpression ();
1959+ call ->operands [num - i - 1 ] = popExpression ();
19531960 }
1954- curr->type = type->result ;
1955- functionCalls[index].push_back (curr);
1961+ call->type = type->result ;
19561962 }
1957- void visitCallImport (CallImport *curr) {
1958- if (debug) std::cerr << " zz node: CallImport" << std::endl;
1963+
1964+ Expression* visitCall () {
1965+ if (debug) std::cerr << " zz node: Call" << std::endl;
19591966 auto arity = getU32LEB ();
19601967 WASM_UNUSED (arity);
1961- auto import = wasm.getImport (getU32LEB ());
1962- curr->target = import ->name ;
1963- auto type = import ->functionType ;
1964- assert (type);
1965- auto num = type->params .size ();
1966- assert (num == arity);
1967- if (debug) std::cerr << " zz node: CallImport " << curr->target << " with type " << type->name << " and " << num << " params\n " ;
1968- curr->operands .resize (num);
1969- for (size_t i = 0 ; i < num; i++) {
1970- curr->operands [num - i - 1 ] = popExpression ();
1968+ auto index = getU32LEB ();
1969+ FunctionType* type;
1970+ Expression* ret;
1971+ if (index < functionImportIndexes.size ()) {
1972+ // this is a call of an imported function
1973+ auto * call = allocator.alloc <CallImport>();
1974+ auto * import = wasm.getImport (functionImportIndexes[index]);
1975+ call->target = import ->name ;
1976+ type = import ->functionType ;
1977+ fillCall (call, type, arity);
1978+ ret = call;
1979+ } else {
1980+ // this is a call of a defined function
1981+ auto * call = allocator.alloc <Call>();
1982+ auto adjustedIndex = index - functionImportIndexes.size ();
1983+ assert (adjustedIndex < functionTypes.size ());
1984+ type = functionTypes[adjustedIndex];
1985+ fillCall (call, type, arity);
1986+ functionCalls[adjustedIndex].push_back (call); // we don't know function names yet
1987+ ret = call;
19711988 }
1972- curr-> type = type-> result ;
1989+ return ret ;
19731990 }
19741991 void visitCallIndirect (CallIndirect *curr) {
19751992 if (debug) std::cerr << " zz node: CallIndirect" << std::endl;
0 commit comments