(&mut self, type_addr: u32, table_addr: u32)
| 1030 | } |
| 1031 | |
| 1032 | fn exec_call_indirect<const IS_RETURN_CALL: bool>(&mut self, type_addr: u32, table_addr: u32) -> Result<(), Trap> { |
| 1033 | self.charge_call_fuel(FUEL_COST_CALL_TOTAL); |
| 1034 | |
| 1035 | // verify that the table is of the right type, this should be validated by the parser already |
| 1036 | let table_idx: u32 = <i32>::stack_pop(&mut self.store.value_stack) as u32; |
| 1037 | let table = self.store.state.get_table(self.module.resolve_table_addr(table_addr)); |
| 1038 | debug_assert!(table.kind.element_type == WasmType::RefFunc, "table is not of type funcref"); |
| 1039 | |
| 1040 | let Ok(table) = table.get(table_idx) else { |
| 1041 | cold_path(); |
| 1042 | return Err(Trap::UndefinedElement { index: table_idx as usize }); |
| 1043 | }; |
| 1044 | |
| 1045 | let Some(func_ref) = table.addr() else { |
| 1046 | cold_path(); |
| 1047 | return Err(Trap::UninitializedElement { index: table_idx as usize }); |
| 1048 | }; |
| 1049 | |
| 1050 | let call_ty = self.module.func_type_by_type_index(type_addr); |
| 1051 | match self.store.state.get_func(func_ref) { |
| 1052 | crate::FunctionInstance::Wasm(wasm_func) => { |
| 1053 | if wasm_func.ty() != call_ty { |
| 1054 | cold_path(); |
| 1055 | return Err(Trap::IndirectCallTypeMismatch { |
| 1056 | actual: wasm_func.ty().clone(), |
| 1057 | expected: call_ty.clone(), |
| 1058 | }); |
| 1059 | } |
| 1060 | |
| 1061 | match IS_RETURN_CALL { |
| 1062 | true => self.exec_return_call(wasm_func.clone(), func_ref), |
| 1063 | false => self.exec_call(wasm_func.clone(), func_ref), |
| 1064 | } |
| 1065 | } |
| 1066 | crate::FunctionInstance::Host(host_func) => { |
| 1067 | if host_func.ty != *call_ty { |
| 1068 | cold_path(); |
| 1069 | return Err(Trap::IndirectCallTypeMismatch { |
| 1070 | actual: host_func.ty.clone(), |
| 1071 | expected: call_ty.clone(), |
| 1072 | }); |
| 1073 | } |
| 1074 | |
| 1075 | self.exec_call_host(host_func.clone()) |
| 1076 | } |
| 1077 | } |
| 1078 | } |
| 1079 | |
| 1080 | fn exec_return(&mut self) -> bool { |
| 1081 | self.store.value_stack.truncate_keep_counts(self.cf.locals_base, self.func.results); |
nothing calls this directly
no test coverage detected