summaryrefslogtreecommitdiff
path: root/src/wasm
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm')
-rw-r--r--src/wasm/wasm-binary.cpp18
-rw-r--r--src/wasm/wasm-s-parser.cpp7
-rw-r--r--src/wasm/wasm-validator.cpp6
-rw-r--r--src/wasm/wasm.cpp1
4 files changed, 30 insertions, 2 deletions
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index f1c6eeb7c..d15ac493f 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -679,6 +679,8 @@ void WasmBinaryWriter::writeFeaturesSection() {
return BinaryConsts::UserSections::SignExtFeature;
case FeatureSet::ExceptionHandling:
return BinaryConsts::UserSections::ExceptionHandlingFeature;
+ case FeatureSet::TailCall:
+ return BinaryConsts::UserSections::TailCallFeature;
default:
WASM_UNREACHABLE();
}
@@ -2162,6 +2164,8 @@ void WasmBinaryBuilder::readFeatures(size_t payloadLen) {
wasm.features.setSignExt();
} else if (name == BinaryConsts::UserSections::SIMD128Feature) {
wasm.features.setSIMD();
+ } else if (name == BinaryConsts::UserSections::TailCallFeature) {
+ wasm.features.setTailCall();
}
}
}
@@ -2210,6 +2214,20 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) {
visitCallIndirect(
(curr = allocator.alloc<CallIndirect>())->cast<CallIndirect>());
break;
+ case BinaryConsts::RetCallFunction: {
+ auto call = allocator.alloc<Call>();
+ call->isReturn = true;
+ curr = call;
+ visitCall(call);
+ break;
+ }
+ case BinaryConsts::RetCallIndirect: {
+ auto call = allocator.alloc<CallIndirect>();
+ call->isReturn = true;
+ curr = call;
+ visitCallIndirect(call);
+ break;
+ }
case BinaryConsts::LocalGet:
visitLocalGet((curr = allocator.alloc<LocalGet>())->cast<LocalGet>());
break;
diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp
index 04c31815f..7a2d8a009 100644
--- a/src/wasm/wasm-s-parser.cpp
+++ b/src/wasm/wasm-s-parser.cpp
@@ -1622,17 +1622,19 @@ Expression* SExpressionWasmBuilder::makeLoop(Element& s) {
return ret;
}
-Expression* SExpressionWasmBuilder::makeCall(Element& s) {
+Expression* SExpressionWasmBuilder::makeCall(Element& s, bool isReturn) {
auto target = getFunctionName(*s[1]);
auto ret = allocator.alloc<Call>();
ret->target = target;
ret->type = functionTypes[ret->target];
parseCallOperands(s, 2, s.size(), ret);
+ ret->isReturn = isReturn;
ret->finalize();
return ret;
}
-Expression* SExpressionWasmBuilder::makeCallIndirect(Element& s) {
+Expression* SExpressionWasmBuilder::makeCallIndirect(Element& s,
+ bool isReturn) {
if (!wasm.table.exists) {
throw ParseException("no table");
}
@@ -1645,6 +1647,7 @@ Expression* SExpressionWasmBuilder::makeCallIndirect(Element& s) {
ret->type = functionType->result;
parseCallOperands(s, i, s.size() - 1, ret);
ret->target = parseExpression(s[s.size() - 1]);
+ ret->isReturn = isReturn;
ret->finalize();
return ret;
}
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index 1d12c2452..01cb1e2a8 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -569,6 +569,9 @@ void FunctionValidator::visitSwitch(Switch* curr) {
}
void FunctionValidator::visitCall(Call* curr) {
+ shouldBeTrue(!curr->isReturn || getModule()->features.hasTailCall(),
+ curr,
+ "return_call requires tail calls to be enabled");
if (!info.validateGlobally) {
return;
}
@@ -593,6 +596,9 @@ void FunctionValidator::visitCall(Call* curr) {
}
void FunctionValidator::visitCallIndirect(CallIndirect* curr) {
+ shouldBeTrue(!curr->isReturn || getModule()->features.hasTailCall(),
+ curr,
+ "return_call_indirect requires tail calls to be enabled");
if (!info.validateGlobally) {
return;
}
diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp
index a307d95f4..e4c9813b3 100644
--- a/src/wasm/wasm.cpp
+++ b/src/wasm/wasm.cpp
@@ -40,6 +40,7 @@ const char* MutableGlobalsFeature = "mutable-globals";
const char* TruncSatFeature = "nontrapping-fptoint";
const char* SignExtFeature = "sign-ext";
const char* SIMD128Feature = "simd128";
+const char* TailCallFeature = "tail-call";
} // namespace UserSections
} // namespace BinaryConsts