diff options
Diffstat (limited to 'src/wasm')
-rw-r--r-- | src/wasm/wasm-binary.cpp | 18 | ||||
-rw-r--r-- | src/wasm/wasm-s-parser.cpp | 7 | ||||
-rw-r--r-- | src/wasm/wasm-validator.cpp | 6 | ||||
-rw-r--r-- | src/wasm/wasm.cpp | 1 |
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 |