Skip to content

Commit 5c33c04

Browse files
authored
Refactor type/signature/local parsing methods (NFC) (#2129)
- Created `parseParamOrLocals`, `parseNamedParamOrLocals`, `parseResult`, and `parseTypeRef` and make other methods use them - Deleted some unnecessary member variables
1 parent 677808a commit 5c33c04

2 files changed

Lines changed: 111 additions & 89 deletions

File tree

src/wasm-s-parser.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
#include "mixed_arena.h"
2626
#include "parsing.h" // for UniqueNameMapper. TODO: move dependency to cpp file?
27+
#include "wasm-builder.h"
2728
#include "wasm.h"
2829

2930
namespace wasm {
@@ -135,9 +136,6 @@ class SExpressionWasmBuilder {
135136

136137
// function parsing state
137138
std::unique_ptr<Function> currFunction;
138-
std::map<Name, Type> currLocalTypes;
139-
size_t localIndex; // params and vars
140-
size_t otherIndex;
141139
bool brokeToAutoBlock;
142140

143141
UniqueNameMapper nameMapper;
@@ -220,8 +218,13 @@ class SExpressionWasmBuilder {
220218
Expression* makeBreakTable(Element& s);
221219
Expression* makeReturn(Element& s);
222220

221+
// Helper functions
223222
Type parseOptionalResultType(Element& s, Index& i);
224223
Index parseMemoryLimits(Element& s, Index i);
224+
std::vector<Type> parseParamOrLocal(Element& s);
225+
std::vector<NameType> parseNamedParamOrLocal(Element& s, size_t& localIndex);
226+
Type parseResult(Element& s);
227+
FunctionType* parseTypeRef(Element& s);
225228

226229
void stringToBinary(const char* input, size_t size, std::vector<char>& data);
227230
void parseMemory(Element& s, bool preParseImport = false);

src/wasm/wasm-s-parser.cpp

Lines changed: 105 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
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+
473544
void 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

Comments
 (0)