Invoke function. See "include/executor/executor.h".
| 107 | |
| 108 | /// Invoke function. See "include/executor/executor.h". |
| 109 | Expect<std::vector<std::pair<ValVariant, ValType>>> |
| 110 | Executor::invoke(const Runtime::Instance::FunctionInstance *FuncInst, |
| 111 | Span<const ValVariant> Params, |
| 112 | Span<const ValType> ParamTypes) { |
| 113 | if (unlikely(FuncInst == nullptr)) { |
| 114 | spdlog::error(ErrCode::Value::FuncNotFound); |
| 115 | return Unexpect(ErrCode::Value::FuncNotFound); |
| 116 | } |
| 117 | |
| 118 | // Matching arguments and function type. |
| 119 | const auto &FuncType = FuncInst->getFuncType(); |
| 120 | const auto &PTypes = FuncType.getParamTypes(); |
| 121 | const auto &RTypes = FuncType.getReturnTypes(); |
| 122 | // The defined type list may be empty if the function is an independent |
| 123 | // function instance, that is, the module instance will be nullptr. In this |
| 124 | // case, all value types are number types or abstract heap types. |
| 125 | // |
| 126 | // If a function belongs to a component instance, its type should already be |
| 127 | // converted, so the type list is not needed. |
| 128 | WasmEdge::Span<const WasmEdge::AST::SubType *const> TypeList = {}; |
| 129 | if (FuncInst->getModule()) { |
| 130 | TypeList = FuncInst->getModule()->getTypeList(); |
| 131 | } |
| 132 | if (!AST::TypeMatcher::matchTypes(TypeList, ParamTypes, PTypes)) { |
| 133 | spdlog::error(ErrCode::Value::FuncSigMismatch); |
| 134 | spdlog::error(ErrInfo::InfoMismatch( |
| 135 | PTypes, RTypes, std::vector(ParamTypes.begin(), ParamTypes.end()), |
| 136 | RTypes)); |
| 137 | return Unexpect(ErrCode::Value::FuncSigMismatch); |
| 138 | } |
| 139 | |
| 140 | // Check the reference value validation. |
| 141 | for (uint32_t I = 0; I < ParamTypes.size(); ++I) { |
| 142 | if (ParamTypes[I].isRefType() && (!ParamTypes[I].isNullableRefType() && |
| 143 | Params[I].get<RefVariant>().isNull())) { |
| 144 | spdlog::error(ErrCode::Value::NonNullRequired); |
| 145 | spdlog::error(" Cannot pass a null reference as argument of {}."sv, |
| 146 | ParamTypes[I]); |
| 147 | return Unexpect(ErrCode::Value::NonNullRequired); |
| 148 | } |
| 149 | } |
| 150 | |
| 151 | Runtime::StackManager StackMgr; |
| 152 | |
| 153 | // Call runFunction. |
| 154 | EXPECTED_TRY(runFunction(StackMgr, *FuncInst, Params).map_error([](auto E) { |
| 155 | if (E != ErrCode::Value::Terminated) { |
| 156 | dumpStackTrace(Span<const uint32_t>{StackTrace}.first(StackTraceSize)); |
| 157 | } |
| 158 | return E; |
| 159 | })); |
| 160 | |
| 161 | // Get return values. |
| 162 | std::vector<std::pair<ValVariant, ValType>> Returns(RTypes.size()); |
| 163 | for (uint32_t I = 0; I < RTypes.size(); ++I) { |
| 164 | auto Val = StackMgr.pop(); |
| 165 | const auto &RType = RTypes[RTypes.size() - I - 1]; |
| 166 | if (RType.isRefType()) { |
no test coverage detected