summaryrefslogtreecommitdiff
path: root/src/wast-parser.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/wast-parser.cc')
-rw-r--r--src/wast-parser.cc95
1 files changed, 72 insertions, 23 deletions
diff --git a/src/wast-parser.cc b/src/wast-parser.cc
index ee3acdba..577b18c7 100644
--- a/src/wast-parser.cc
+++ b/src/wast-parser.cc
@@ -19,6 +19,7 @@
#include "src/binary-reader.h"
#include "src/binary-reader-ir.h"
#include "src/cast.h"
+#include "src/expr-visitor.h"
#include "src/error-handler.h"
#include "src/make-unique.h"
#include "src/utf8.h"
@@ -253,15 +254,56 @@ bool IsEmptySignature(const FuncSignature* sig) {
return sig->result_types.empty() && sig->param_types.empty();
}
+void ResolveFuncType(const Location& loc,
+ Module* module,
+ FuncDeclaration* decl) {
+ // Resolve func type variables where the signature was not specified
+ // explicitly, e.g.: (func (type 1) ...)
+ if (decl->has_func_type && IsEmptySignature(&decl->sig)) {
+ FuncType* func_type = module->GetFuncType(decl->type_var);
+ if (func_type) {
+ decl->sig = func_type->sig;
+ }
+ }
+
+ // Resolve implicitly defined function types, e.g.: (func (param i32) ...)
+ if (!decl->has_func_type) {
+ Index func_type_index = module->GetFuncTypeIndex(decl->sig);
+ if (func_type_index == kInvalidIndex) {
+ auto func_type_field = MakeUnique<FuncTypeModuleField>(loc);
+ func_type_field->func_type.sig = decl->sig;
+ module->AppendField(std::move(func_type_field));
+ }
+ }
+}
+
+class ResolveFuncTypesExprVisitorDelegate : public ExprVisitor::DelegateNop {
+ public:
+ explicit ResolveFuncTypesExprVisitorDelegate(Module* module)
+ : module_(module) {}
+
+ Result OnCallIndirectExpr(CallIndirectExpr* expr) override {
+ ResolveFuncType(expr->loc, module_, &expr->decl);
+ return Result::Ok;
+ }
+
+ private:
+ Module* module_;
+};
+
void ResolveFuncTypes(Module* module) {
for (ModuleField& field : module->fields) {
Func* func = nullptr;
+ FuncDeclaration* decl = nullptr;
if (auto* func_field = dyn_cast<FuncModuleField>(&field)) {
func = &func_field->func;
+ decl = &func->decl;
} else if (auto* import_field = dyn_cast<ImportModuleField>(&field)) {
if (auto* func_import =
dyn_cast<FuncImport>(import_field->import.get())) {
- func = &func_import->func;
+ // Only check the declaration, not the function itself, since it is an
+ // import.
+ decl = &func_import->func.decl;
} else {
continue;
}
@@ -269,23 +311,13 @@ void ResolveFuncTypes(Module* module) {
continue;
}
- // Resolve func type variables where the signature was not specified
- // explicitly, e.g.: (func (type 1) ...)
- if (func->decl.has_func_type && IsEmptySignature(&func->decl.sig)) {
- FuncType* func_type = module->GetFuncType(func->decl.type_var);
- if (func_type) {
- func->decl.sig = func_type->sig;
- }
- }
+ if (decl)
+ ResolveFuncType(field.loc, module, decl);
- // Resolve implicitly defined function types, e.g.: (func (param i32) ...)
- if (!func->decl.has_func_type) {
- Index func_type_index = module->GetFuncTypeIndex(func->decl.sig);
- if (func_type_index == kInvalidIndex) {
- auto func_type_field = MakeUnique<FuncTypeModuleField>(field.loc);
- func_type_field->func_type.sig = func->decl.sig;
- module->AppendField(std::move(func_type_field));
- }
+ if (func) {
+ ResolveFuncTypesExprVisitorDelegate delegate(module);
+ ExprVisitor visitor(&delegate);
+ visitor.VisitFunc(func);
}
}
}
@@ -1143,6 +1175,13 @@ Result WastParser::ParseFuncSignature(FuncSignature* sig,
return Result::Ok;
}
+Result WastParser::ParseUnboundFuncSignature(FuncSignature* sig) {
+ WABT_TRACE(ParseUnboundFuncSignature);
+ CHECK_RESULT(ParseUnboundValueTypeList(TokenType::Param, &sig->param_types));
+ CHECK_RESULT(ParseResultList(&sig->result_types));
+ return Result::Ok;
+}
+
Result WastParser::ParseBoundValueTypeList(TokenType token,
TypeVector* types,
BindingHash* bindings) {
@@ -1164,15 +1203,21 @@ Result WastParser::ParseBoundValueTypeList(TokenType token,
return Result::Ok;
}
-Result WastParser::ParseResultList(TypeVector* result_types) {
- WABT_TRACE(ParseResultList);
- while (MatchLpar(TokenType::Result)) {
- CHECK_RESULT(ParseValueTypeList(result_types));
+Result WastParser::ParseUnboundValueTypeList(TokenType token,
+ TypeVector* types) {
+ WABT_TRACE(ParseUnboundValueTypeList);
+ while (MatchLpar(token)) {
+ CHECK_RESULT(ParseValueTypeList(types));
EXPECT(Rpar);
}
return Result::Ok;
}
+Result WastParser::ParseResultList(TypeVector* result_types) {
+ WABT_TRACE(ParseResultList);
+ return ParseUnboundValueTypeList(TokenType::Result, result_types);
+}
+
Result WastParser::ParseInstrList(ExprList* exprs) {
WABT_TRACE(ParseInstrList);
ExprList new_exprs;
@@ -1293,10 +1338,14 @@ Result WastParser::ParsePlainInstr(std::unique_ptr<Expr>* out_expr) {
CHECK_RESULT(ParsePlainInstrVar<CallExpr>(loc, out_expr));
break;
- case TokenType::CallIndirect:
+ case TokenType::CallIndirect: {
Consume();
- CHECK_RESULT(ParsePlainInstrVar<CallIndirectExpr>(loc, out_expr));
+ auto expr = MakeUnique<CallIndirectExpr>(loc);
+ CHECK_RESULT(ParseTypeUseOpt(&expr->decl));
+ CHECK_RESULT(ParseUnboundFuncSignature(&expr->decl.sig));
+ *out_expr = std::move(expr);
break;
+ }
case TokenType::GetLocal:
Consume();