2626#include " ir/function-type-utils.h"
2727#include " shared-constants.h"
2828#include " wasm-binary.h"
29- #include " wasm-builder.h"
3029
3130#define abort_on (str ) \
3231 { throw ParseException (std::string (" abort_on " ) + str); }
@@ -470,6 +469,78 @@ Name SExpressionWasmBuilder::getGlobalName(Element& s) {
470469 }
471470}
472471
472+ // Parse various forms of (param ...) or (local ...) element. This ignores all
473+ // parameter or local names when specified.
474+ std::vector<Type> SExpressionWasmBuilder::parseParamOrLocal (Element& s) {
475+ size_t fakeIndex = 0 ;
476+ std::vector<NameType> namedParams = parseNamedParamOrLocal (s, fakeIndex);
477+ std::vector<Type> params;
478+ for (auto & nameType : namedParams) {
479+ params.push_back (nameType.type );
480+ }
481+ return params;
482+ }
483+
484+ // Parses various forms of (param ...) or (local ...) element:
485+ // (param $name type) (e.g. (param $a i32))
486+ // (param type+) (e.g. (param i32 f64))
487+ // (local $name type) (e.g. (local $a i32))
488+ // (local type+) (e.g. (local i32 f64))
489+ // If the name is unspecified, it will create one using localIndex.
490+ std::vector<NameType>
491+ SExpressionWasmBuilder::parseNamedParamOrLocal (Element& s, size_t & localIndex) {
492+ assert (s.isList () && (s[0 ]->str () == PARAM || s[0 ]->str () == LOCAL));
493+ std::vector<NameType> namedParams;
494+ if (s.size () == 1 ) { // (param) or (local)
495+ return namedParams;
496+ }
497+
498+ for (size_t i = 1 ; i < s.size (); i++) {
499+ IString name;
500+ if (s[i]->dollared ()) {
501+ if (i != 1 ) {
502+ throw ParseException (" invalid wasm type" , s[i]->line , s[i]->col );
503+ }
504+ if (i + 1 >= s.size ()) {
505+ throw ParseException (" invalid param entry" , s.line , s.col );
506+ }
507+ name = s[i]->str ();
508+ i++;
509+ } else {
510+ name = Name::fromInt (localIndex);
511+ }
512+ localIndex++;
513+ Type type = stringToType (s[i]->str ());
514+ namedParams.emplace_back (name, type);
515+ }
516+ return namedParams;
517+ }
518+
519+ // Parses (result type) element. (e.g. (result i32))
520+ Type SExpressionWasmBuilder::parseResult (Element& s) {
521+ assert (s.isList () && s[0 ]->str () == RESULT);
522+ if (s.size () != 2 ) {
523+ throw ParseException (" invalid result arity" , s.line , s.col );
524+ }
525+ return stringToType (s[1 ]->str ());
526+ }
527+
528+ // Parses an element that references an entry in the type section. The element
529+ // should be in the form of (type name) or (type index).
530+ // (e.g. (type $a), (type 0))
531+ FunctionType* SExpressionWasmBuilder::parseTypeRef (Element& s) {
532+ assert (s.isList () && s[0 ]->str () == TYPE);
533+ if (s.size () != 2 ) {
534+ throw ParseException (" invalid type reference" , s.line , s.col );
535+ }
536+ IString name = getFunctionTypeName (*s[1 ]);
537+ FunctionType* ft = wasm.getFunctionTypeOrNull (name);
538+ if (!ft) {
539+ throw ParseException (" bad function type for import" , s[1 ]->line , s[1 ]->col );
540+ }
541+ return ft;
542+ }
543+
473544void SExpressionWasmBuilder::preParseFunctionType (Element& s) {
474545 IString id = s[0 ]->str ();
475546 if (id == TYPE) {
@@ -494,27 +565,12 @@ void SExpressionWasmBuilder::preParseFunctionType(Element& s) {
494565 Element& curr = *s[i];
495566 IString id = curr[0 ]->str ();
496567 if (id == RESULT) {
497- if (curr.size () > 2 ) {
498- throw ParseException (" invalid result arity" , curr.line , curr.col );
499- }
500- functionTypes[name] = stringToType (curr[1 ]->str ());
568+ functionTypes[name] = parseResult (curr);
501569 } else if (id == TYPE) {
502- Name typeName = getFunctionTypeName (*curr[1 ]);
503- if (!wasm.getFunctionTypeOrNull (typeName)) {
504- throw ParseException (" unknown function type" , curr.line , curr.col );
505- }
506- type = wasm.getFunctionType (typeName);
507- functionTypes[name] = type->result ;
570+ functionTypes[name] = parseTypeRef (curr)->result ;
508571 } else if (id == PARAM && curr.size () > 1 ) {
509- Index j = 1 ;
510- if (curr[j]->dollared ()) {
511- // dollared input symbols cannot be types
512- params.push_back (stringToType (curr[j + 1 ]->str (), true ));
513- } else {
514- while (j < curr.size ()) {
515- params.push_back (stringToType (curr[j++]->str (), true ));
516- }
517- }
572+ auto newParams = parseParamOrLocal (curr);
573+ params.insert (params.end (), newParams.begin (), newParams.end ());
518574 }
519575 }
520576 if (!type) {
@@ -601,8 +657,7 @@ void SExpressionWasmBuilder::parseFunction(Element& s, bool preParseImport) {
601657 wasm.addExport (ex.release ());
602658 }
603659 Expression* body = nullptr ;
604- localIndex = 0 ;
605- otherIndex = 0 ;
660+ size_t localIndex = 0 ; // params and vars
606661 brokeToAutoBlock = false ;
607662 // we may have both params and a type. store the type info here
608663 std::vector<NameType> typeParams;
@@ -627,49 +682,22 @@ void SExpressionWasmBuilder::parseFunction(Element& s, bool preParseImport) {
627682 for (; i < s.size (); i++) {
628683 Element& curr = *s[i];
629684 IString id = curr[0 ]->str ();
630- if (id == PARAM || id == LOCAL) {
631- size_t j = 1 ;
632- while (j < curr.size ()) {
633- IString name;
634- Type type = none;
635- if (!curr[j]->dollared ()) { // dollared input symbols cannot be types
636- type = stringToType (curr[j]->str (), true );
637- }
638- if (type != none) {
639- // a type, so an unnamed parameter
640- name = Name::fromInt (localIndex);
641- } else {
642- name = curr[j]->str ();
643- type = stringToType (curr[j + 1 ]->str ());
644- j++;
645- }
646- j++;
647- if (id == PARAM) {
648- params.emplace_back (name, type);
649- } else {
650- vars.emplace_back (name, type);
651- }
652- localIndex++;
653- currLocalTypes[name] = type;
654- }
685+ if (id == PARAM) {
686+ auto newParams = parseNamedParamOrLocal (curr, localIndex);
687+ params.insert (params.end (), newParams.begin (), newParams.end ());
688+ } else if (id == LOCAL) {
689+ auto newVars = parseNamedParamOrLocal (curr, localIndex);
690+ vars.insert (vars.end (), newVars.begin (), newVars.end ());
655691 } else if (id == RESULT) {
656- if (curr.size () > 2 ) {
657- throw ParseException (" invalid result arity" , curr.line , curr.col );
658- }
659- result = stringToType (curr[1 ]->str ());
692+ result = parseResult (curr);
660693 } else if (id == TYPE) {
661- Name name = getFunctionTypeName (*curr[1 ]);
662- type = name;
663- if (!wasm.getFunctionTypeOrNull (name)) {
664- throw ParseException (" unknown function type" );
665- }
666- FunctionType* type = wasm.getFunctionType (name);
667- result = type->result ;
668- for (size_t j = 0 ; j < type->params .size (); j++) {
694+ FunctionType* ft = parseTypeRef (curr);
695+ type = ft->name ;
696+ result = ft->result ;
697+ for (size_t j = 0 ; j < ft->params .size (); j++) {
669698 IString name = Name::fromInt (j);
670- Type currType = type ->params [j];
699+ Type currType = ft ->params [j];
671700 typeParams.emplace_back (name, currType);
672- currLocalTypes[name] = currType;
673701 }
674702 } else if (id == IMPORT) {
675703 importModule = curr[1 ]->str ();
@@ -728,7 +756,6 @@ void SExpressionWasmBuilder::parseFunction(Element& s, bool preParseImport) {
728756 if (currFunction) {
729757 throw ParseException (" import module inside function dec" );
730758 }
731- currLocalTypes.clear ();
732759 nameMapper.clear ();
733760 return ;
734761 }
@@ -761,7 +788,6 @@ void SExpressionWasmBuilder::parseFunction(Element& s, bool preParseImport) {
761788 throw ParseException (" duplicate function" , s.line , s.col );
762789 }
763790 wasm.addFunction (currFunction.release ());
764- currLocalTypes.clear ();
765791 nameMapper.clear ();
766792}
767793
@@ -1537,11 +1563,11 @@ Expression* SExpressionWasmBuilder::makeCallIndirect(Element& s) {
15371563 while (1 ) {
15381564 Element& curr = *s[i];
15391565 if (curr[0 ]->str () == PARAM) {
1540- for ( size_t j = 1 ; j < curr. size (); j++) {
1541- type.params .push_back ( stringToType (curr[j]-> str ()));
1542- }
1566+ auto newParams = parseParamOrLocal (curr);
1567+ type.params .insert (
1568+ type. params . end (), newParams. begin (), newParams. end ());
15431569 } else if (curr[0 ]->str () == RESULT) {
1544- type.result = stringToType (curr[ 1 ]-> str () );
1570+ type.result = parseResult (curr);
15451571 } else {
15461572 break ;
15471573 }
@@ -1921,20 +1947,16 @@ void SExpressionWasmBuilder::parseImport(Element& s) {
19211947 if (kind == ExternalKind::Function) {
19221948 std::unique_ptr<FunctionType> type = make_unique<FunctionType>();
19231949 if (inner.size () > j) {
1924- Element& params = *inner[j];
1925- IString id = params [0 ]->str ();
1950+ Element& elems = *inner[j];
1951+ IString id = elems [0 ]->str ();
19261952 if (id == PARAM) {
1927- for ( size_t k = 1 ; k < params. size (); k++) {
1928- type->params .push_back ( stringToType (params[k]-> str ()));
1929- }
1953+ auto newParams = parseParamOrLocal (elems);
1954+ type->params .insert (
1955+ type-> params . end (), newParams. begin (), newParams. end ());
19301956 } else if (id == RESULT) {
1931- type->result = stringToType (params[ 1 ]-> str () );
1957+ type->result = parseResult (elems );
19321958 } else if (id == TYPE) {
1933- IString name = params[1 ]->str ();
1934- if (!wasm.getFunctionTypeOrNull (name)) {
1935- throw ParseException (" bad function type for import" );
1936- }
1937- *type = *wasm.getFunctionType (name);
1959+ type.reset (parseTypeRef (elems));
19381960 } else {
19391961 throw ParseException (" bad import element" );
19401962 }
@@ -1943,7 +1965,7 @@ void SExpressionWasmBuilder::parseImport(Element& s) {
19431965 if (result[0 ]->str () != RESULT) {
19441966 throw ParseException (" expected result" );
19451967 }
1946- type->result = stringToType (result[ 1 ]-> str () );
1968+ type->result = parseResult (result);
19471969 }
19481970 }
19491971 auto func = make_unique<Function>();
@@ -2203,14 +2225,11 @@ void SExpressionWasmBuilder::parseType(Element& s) {
22032225 for (size_t k = 1 ; k < func.size (); k++) {
22042226 Element& curr = *func[k];
22052227 if (curr[0 ]->str () == PARAM) {
2206- for ( size_t j = 1 ; j < curr. size (); j++) {
2207- type->params .push_back ( stringToType (curr[j]-> str ()));
2208- }
2228+ auto newParams = parseParamOrLocal (curr);
2229+ type->params .insert (
2230+ type-> params . end (), newParams. begin (), newParams. end ());
22092231 } else if (curr[0 ]->str () == RESULT) {
2210- if (curr.size () > 2 ) {
2211- throw ParseException (" invalid result arity" , curr.line , curr.col );
2212- }
2213- type->result = stringToType (curr[1 ]->str ());
2232+ type->result = parseResult (curr);
22142233 }
22152234 }
22162235 if (!type->name .is ()) {
0 commit comments