You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

vm.cc 18 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601
  1. /**
  2. * This is the C++ adaptation and derivative work of Myia (https://github.com/mila-iqia/myia/).
  3. *
  4. * Copyright 2019 Huawei Technologies Co., Ltd
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the "License");
  7. * you may not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. #include "vm/vm.h"
  19. #include <algorithm>
  20. #include "vm/vmimpl.h"
  21. #include "vm/backend.h"
  22. #include "vm/transform.h"
  23. #include "pipeline/parse/data_converter.h"
  24. namespace mindspore {
  25. namespace compile {
  26. // Initialize StructPartial.
  27. // Arguments:
  28. // fn_: Callable function.
  29. // args_: Sequence of function args.
  30. // fg_: Graph of function.
  31. StructPartial::StructPartial(int fn, const VectorRef &args, const FuncGraphPtr &fg) : fn_(fn), args_(args), fg_(fg) {}
  32. std::ostream &operator<<(std::ostream &os, const StructPartial &other) {
  33. os << "partial(" << other.fn_ << ", " << other.args_.ToString() << ")";
  34. return os;
  35. }
  36. bool operator==(const StructPartial &lhs, const StructPartial &rhs) {
  37. return (lhs.fn_ == rhs.fn_ && lhs.args_ == rhs.args_ && lhs.fg_ == rhs.fg_);
  38. }
  39. StructSimuSwitch::StructSimuSwitch(const BaseRef &fn, const BaseRef &value) : fn_(fn), value_(value) {}
  40. std::ostream &operator<<(std::ostream &os, const StructSimuSwitch &other) {
  41. os << "SimulSwitch(" << other.fn_.ToString() << ", " << other.value_.ToString() << ")";
  42. return os;
  43. }
  44. bool operator==(const StructSimuSwitch &lhs, const StructSimuSwitch &rhs) {
  45. return (lhs.fn_ == rhs.fn_ && lhs.value_ == rhs.value_);
  46. }
  47. std::ostream &operator<<(std::ostream &os, const SwitchCondStatus &other) {
  48. os << "SwitchCondStatus(" << static_cast<int>(other) << ")";
  49. return os;
  50. }
  51. // Follow the specified instructions to create a VM.
  52. // Arguments:
  53. // insts_: std::vector<std::map<std::string, VectorRef>>
  54. // insts_stack_: The value stack.
  55. // retp_: The call stack.
  56. // pc_: program counter (next instruction)
  57. // sp_: stack pointer (for the value stack)
  58. FinalVM::FinalVM(const InstSet &insts, const BackendPtr &backend) : insts_(insts), pc_(0), sp_(0), backend_(backend) {
  59. MS_LOG(DEBUG) << "InstSet size:" << insts_.size();
  60. insts_stack_.emplace_back(BaseRef());
  61. retp_.push(-1);
  62. }
  63. void FinalVM::Push(const BaseRef &v) {
  64. MS_LOG(DEBUG) << "Push " << v.ToString() << " sp_:" << sp_;
  65. insts_stack_[IntToSize(sp_++)] = v;
  66. }
  67. void FinalVM::Pop(int n) {
  68. if (n > sp_) {
  69. MS_LOG(EXCEPTION) << "Invalid value of n " << n << ", it should be not more than " << sp_ - 1;
  70. }
  71. for (int i = 0; i < n; i++) {
  72. insts_stack_[IntToSize(sp_ - i - 1)] = BaseRef();
  73. }
  74. sp_ -= n;
  75. }
  76. void FinalVM::MoveStack(int nitems, int height) {
  77. if (nitems > height || height > sp_) {
  78. MS_LOG(EXCEPTION) << "MoveStack arg error: nitems=" << nitems << " height=" << height;
  79. }
  80. int n = height - nitems;
  81. int src = sp_ - height;
  82. int dst = sp_ - nitems;
  83. for (int i = 0; i < nitems; i++) {
  84. insts_stack_[IntToSize(src + i)] = insts_stack_[IntToSize(dst + i)];
  85. }
  86. Pop(n);
  87. }
  88. BaseRef FinalVM::Ref(int i) {
  89. MS_LOG(DEBUG) << "Ref i:" << i << " sp_:" << sp_;
  90. size_t sp_next = IntToSize(sp_ + i);
  91. if (sp_next < insts_stack_.size()) {
  92. if (utils::isa<PyObjectRef>(insts_stack_[sp_next])) {
  93. py::object value = utils::cast<PyObjectRef>(insts_stack_[sp_next]).object_;
  94. MS_LOG(DEBUG) << "VM ref python:" << py::str(value);
  95. return parse::data_converter::PyDataToValue(value);
  96. }
  97. MS_LOG(DEBUG) << "Ref not python :" << insts_stack_[sp_next].ToString();
  98. return insts_stack_[sp_next];
  99. }
  100. MS_LOG(EXCEPTION) << "IndexError: index(" << sp_next << ") out of range [0, " << insts_stack_.size() << ").";
  101. }
  102. void FinalVM::Pushp() { retp_.push(pc_); }
  103. void FinalVM::Popp() {
  104. if (retp_.empty()) {
  105. MS_LOG(EXCEPTION) << "Stack retp_ is empty";
  106. }
  107. pc_ = retp_.top();
  108. MS_LOG(DEBUG) << "Pop pc:" << pc_ << ", sp:" << sp_;
  109. retp_.pop();
  110. }
  111. void FinalVM::Pushsp() { retsp_.push(sp_); }
  112. void FinalVM::Popsp() {
  113. int sp = retsp_.top();
  114. MS_LOG(DEBUG) << "Current sp:" << sp_ << ", before sp:" << sp << ", " << sp_ - sp;
  115. if (sp_ >= sp) {
  116. Pop(sp_ - sp + 1);
  117. retsp_.pop();
  118. } else {
  119. MS_LOG(EXCEPTION) << "Stack point sp_:" << sp << " must biger than sp:" << sp_;
  120. }
  121. }
  122. void FinalVM::PushStatus(bool is_switch_call) { ret_status_.push(is_switch_call); }
  123. bool FinalVM::PopStatus() {
  124. if (ret_status_.empty()) {
  125. return false;
  126. }
  127. bool status = ret_status_.top();
  128. ret_status_.pop();
  129. return status;
  130. }
  131. void FinalVM::DoJmp(const BaseRef &jmp_orig) {
  132. MS_LOG(DEBUG) << "Start";
  133. BaseRef jmp = jmp_orig;
  134. if (backend_->simu_flag()) {
  135. bool is_switch_call = false;
  136. if (utils::isa<StructSimuSwitch>(jmp)) { // need to inherit from Base
  137. MS_LOG(DEBUG) << "Start jump StructSwitch";
  138. auto simu_value = utils::cast<std::shared_ptr<StructSimuSwitch>>(jmp);
  139. jmp = simu_value->fn_;
  140. backend_->set_curr_switch(simu_value->value_);
  141. is_switch_call = true;
  142. }
  143. PushStatus(is_switch_call);
  144. }
  145. if (utils::isa<StructPartial>(jmp)) { // need to inherit from Base
  146. MS_LOG(DEBUG) << "Start jump StructPartial";
  147. auto new_jmp = utils::cast<std::shared_ptr<StructPartial>>(jmp);
  148. auto args = new_jmp->args_;
  149. InstPadStack(VectorRef(std::vector<BaseRef>{static_cast<int>(args.size())}));
  150. auto iter = args.rbegin();
  151. for (; iter != args.rend(); ++iter) {
  152. Push(*iter);
  153. }
  154. pc_ = new_jmp->fn_;
  155. return;
  156. }
  157. if (!utils::isa<int>(jmp)) {
  158. MS_LOG(EXCEPTION) << "Jmp inst should be a int";
  159. }
  160. pc_ = utils::cast<int>(jmp);
  161. MS_LOG(DEBUG) << "End do jump pc_:" << pc_;
  162. }
  163. BaseRef FinalVM::Eval(const VectorRef &args) {
  164. MS_LOG(DEBUG) << "Start: " << args.size();
  165. insts_stack_.clear();
  166. insts_stack_.resize(args.size());
  167. std::stack<int>().swap(retp_);
  168. retp_.push(-1);
  169. pc_ = 0;
  170. sp_ = 0;
  171. auto riter = args.rbegin();
  172. for (; riter != args.rend(); ++riter) {
  173. if (utils::isa<PyObjectRef>(*riter)) {
  174. PyObjectRef py_ref = utils::cast<PyObjectRef>(*riter);
  175. py::object value = py_ref.object_;
  176. if (py::isinstance<py::bool_>(value)) {
  177. auto a = py::cast<bool>(value);
  178. Push(static_cast<int>(a));
  179. continue;
  180. }
  181. }
  182. Push(*riter);
  183. }
  184. while (pc_ >= 0) {
  185. auto inst = insts_[IntToSize(pc_)];
  186. MS_LOG(DEBUG) << "Loop " << insts_.size() << ", pc:" << pc_ << ", inst:" << inst_str[inst.first];
  187. ++pc_;
  188. auto iter = inst_function_map.find(inst.first);
  189. if (iter != inst_function_map.end()) {
  190. iter->second(inst.second);
  191. } else {
  192. MS_LOG(EXCEPTION) << "Unknown instruction {" << inst_str[inst.first] << "}";
  193. }
  194. }
  195. MS_LOG(DEBUG) << "End";
  196. return insts_stack_[0];
  197. }
  198. void FinalVM::InstCall(const VectorRef &args) {
  199. MS_LOG(DEBUG) << "Start";
  200. const size_t args_size = 1;
  201. if (args.size() != args_size) {
  202. MS_LOG(ERROR) << __FUNCTION__ << " requires " << args_size << " parameter, while the input size is " << args.size()
  203. << ".";
  204. return;
  205. }
  206. int jmp = utils::cast<int>(args[0]);
  207. MS_LOG(DEBUG) << "Call pushp:" << pc_ << ", jmp:" << jmp << ", sp:" << sp_;
  208. Pushp();
  209. DoJmp(Ref(jmp));
  210. MS_LOG(DEBUG) << "Instcall end sp :" << sp_;
  211. }
  212. void FinalVM::InstTailCall(const VectorRef &args) {
  213. MS_LOG(DEBUG) << "Start";
  214. const size_t args_size = 3;
  215. if (args.size() != args_size) {
  216. MS_LOG(ERROR) << __FUNCTION__ << " requires " << args_size << " parameters, while the input size is " << args.size()
  217. << ".";
  218. return;
  219. }
  220. int jmp = utils::cast<int>(args[0]);
  221. int height = utils::cast<int>(args[1]);
  222. int nargs = utils::cast<int>(args[2]);
  223. auto new_jmp = Ref(jmp);
  224. MoveStack(nargs, height);
  225. MS_LOG(DEBUG) << "TailCall pushp:" << pc_ << ", jmp:" << jmp;
  226. DoJmp(new_jmp);
  227. MS_LOG(DEBUG) << "End";
  228. }
  229. void FinalVM::InstSwitchReturn(const VectorRef &args) {
  230. MS_LOG(DEBUG) << "Start";
  231. if (args.size() != 1) {
  232. MS_LOG(ERROR) << __FUNCTION__ << " requires one parameter, while the input size is " << args.size() << ".";
  233. return;
  234. }
  235. auto rv = Ref(-1);
  236. if (utils::isa<AnfNodePtr>(rv) || utils::isa<VectorRef>(rv)) {
  237. auto &c = args[0];
  238. cond_out_[c] = rv;
  239. }
  240. Pop(1);
  241. Popsp();
  242. }
  243. void FinalVM::InstReturn(const VectorRef &args) {
  244. MS_LOG(DEBUG) << "Start";
  245. const size_t args_size = 2;
  246. if (args.size() != args_size) {
  247. MS_LOG(ERROR) << __FUNCTION__ << " requires " << args_size << " parameters, while the input size is " << args.size()
  248. << ".";
  249. return;
  250. }
  251. int rpos = utils::cast<int>(args[0]);
  252. int height = utils::cast<int>(args[1]);
  253. auto rv = Ref(rpos);
  254. if (backend_->simu_flag()) {
  255. auto c = backend_->curr_switch();
  256. auto status = PopStatus();
  257. if (status) {
  258. auto iter = cond_out_.find(c);
  259. if (iter != cond_out_.end()) {
  260. rv = MergeArgs(rv, iter->second);
  261. cond_out_.erase(iter);
  262. }
  263. }
  264. if (backend_->is_switch_call()) {
  265. backend_->SetSwitchGraph();
  266. }
  267. }
  268. Pop(height);
  269. Push(rv);
  270. Popp();
  271. MS_LOG(DEBUG) << "End";
  272. }
  273. void FinalVM::InstSimuPartial(const VectorRef &args) {
  274. const size_t args_size = 2;
  275. if (args.size() < args_size) {
  276. MS_LOG(ERROR) << __FUNCTION__ << " requires " << args_size << " or more parameters, while the input size is "
  277. << args.size() << ".";
  278. return;
  279. }
  280. auto &node = args[0];
  281. if (!utils::isa<FuncGraphPtr>(node)) {
  282. MS_LOG(ERROR) << "The type of 1st input of node must be FuncGraph";
  283. return;
  284. }
  285. auto fg = utils::cast<FuncGraphPtr>(node);
  286. int fn_ = utils::cast<int>(args[1]);
  287. auto fn = utils::cast<int>(Ref(fn_));
  288. MS_LOG(DEBUG) << "Partial argssize:" << args.size();
  289. std::vector<BaseRef> outs(args.size() - 2);
  290. (void)std::transform(args.begin() + 2, args.end(), outs.begin(),
  291. [&, this](const BaseRef &a) { return Ref(utils::cast<int>(a)); });
  292. Push(std::make_shared<StructPartial>(fn, VectorRef(outs), fg));
  293. }
  294. void FinalVM::InstRealPartial(const VectorRef &args) {
  295. const size_t args_size = 1;
  296. if (args.size() < args_size) {
  297. MS_LOG(ERROR) << __FUNCTION__ << " requires " << args_size << " or more parameters, while the input size is "
  298. << args.size() << ".";
  299. return;
  300. }
  301. int fn_ = utils::cast<int>(args[0]);
  302. auto fn = utils::cast<int>(Ref(fn_));
  303. MS_LOG(DEBUG) << "Partial argssize:" << args.size();
  304. std::vector<BaseRef> outs(args.size() - 1);
  305. (void)std::transform(args.begin() + 1, args.end(), outs.begin(),
  306. [&, this](const BaseRef &a) { return Ref(utils::cast<int>(a)); });
  307. Push(std::make_shared<StructPartial>(fn, VectorRef(outs)));
  308. }
  309. void FinalVM::InstPartial(const VectorRef &args) {
  310. MS_LOG(DEBUG) << "Start";
  311. if (backend_->is_multi_graph_sink()) {
  312. InstSimuPartial(args);
  313. } else {
  314. InstRealPartial(args);
  315. }
  316. MS_LOG(DEBUG) << "End";
  317. }
  318. void FinalVM::InstSimuSwitch(const VectorRef &args) {
  319. const size_t args_size = 4;
  320. if (args.size() != args_size) {
  321. MS_LOG(ERROR) << __FUNCTION__ << " requires " << args_size << " parameters, while the input size is " << args.size()
  322. << ".";
  323. return;
  324. }
  325. bool cond = utils::cast<bool>(args[0]);
  326. int cond_node = utils::cast<int>(args[1]);
  327. int vtrue = utils::cast<int>(args[2]);
  328. int vfalse = utils::cast<int>(args[3]);
  329. MS_LOG(DEBUG) << "Simu switch cond:" << cond;
  330. BaseRef c = Ref(cond_node);
  331. bool bool_value = cond;
  332. SwitchCondStatus cond_stat = backend_->SetSimuCond(c, bool_value);
  333. if (cond_stat == kCondAlreadyRun) {
  334. MS_LOG(DEBUG) << "switch alreay run bool while true jmp";
  335. BaseRef jmp = Ref(vtrue);
  336. if (utils::isa<StructPartial>(jmp)) {
  337. auto new_jmp = utils::cast<std::shared_ptr<StructPartial>>(jmp);
  338. backend_->RecallGraphInput(new_jmp->fg_, new_jmp->args_, c);
  339. }
  340. cond_jmp_[c] = Ref(vfalse);
  341. Push(static_cast<int>(cond_stat));
  342. Popp();
  343. backend_->SetSwitchActive(c, bool_value);
  344. return;
  345. }
  346. if (bool_value) {
  347. Push(std::make_shared<StructSimuSwitch>(Ref(vtrue), c));
  348. Pushsp();
  349. } else {
  350. MergeJmpArgs(Ref(vfalse), c);
  351. Push(std::make_shared<StructSimuSwitch>(Ref(vfalse), c));
  352. }
  353. }
  354. void FinalVM::MergeJmpArgs(const BaseRef &jmp, const BaseRef &c) {
  355. auto iter = cond_jmp_.find(c);
  356. if (iter == cond_jmp_.end()) {
  357. return;
  358. }
  359. auto old_jmp = utils::cast<std::shared_ptr<StructPartial>>(iter->second);
  360. auto new_jmp = utils::cast<std::shared_ptr<StructPartial>>(jmp);
  361. auto &old_args = old_jmp->args_;
  362. auto &new_args = new_jmp->args_;
  363. for (size_t i = 0; i < new_args.size(); ++i) {
  364. auto &old_arg = old_args[i];
  365. auto &new_arg = new_args[i];
  366. new_arg = MergeArgs(old_arg, new_arg);
  367. }
  368. }
  369. BaseRef FinalVM::MergeArgs(const BaseRef &first, const BaseRef &second) {
  370. MS_LOG(DEBUG) << __FUNCTION__ << ": " << first.ToString() << ", " << second.ToString();
  371. if (utils::isa<VectorRef>(first)) {
  372. auto old_vec_ref = utils::cast<VectorRef>(first);
  373. if (utils::isa<VectorRef>(second)) {
  374. auto new_vec_ref = utils::cast<VectorRef>(second);
  375. std::copy(new_vec_ref.begin(), new_vec_ref.end(), std::back_inserter(old_vec_ref));
  376. } else {
  377. old_vec_ref.push_back(second);
  378. }
  379. return old_vec_ref;
  380. }
  381. if (utils::isa<VectorRef>(second)) {
  382. auto new_vec_ref = utils::cast<VectorRef>(second);
  383. new_vec_ref.push_back(first);
  384. return new_vec_ref;
  385. }
  386. return VectorRef({first, second});
  387. }
  388. void FinalVM::InstRealSwitch(const VectorRef &args) {
  389. const size_t args_size = 3;
  390. if (args.size() != args_size) {
  391. MS_LOG(ERROR) << __FUNCTION__ << " requires " << args_size << " parameters, while the input size is " << args.size()
  392. << ".";
  393. return;
  394. }
  395. int cond = utils::cast<int>(args[0]);
  396. int vtrue = utils::cast<int>(args[1]);
  397. int vfalse = utils::cast<int>(args[2]);
  398. BaseRef c = Ref(cond);
  399. MS_LOG(DEBUG) << vtrue << " false:" << vfalse << " InstSwitch: " << c.ToString();
  400. bool bool_value = false;
  401. if (backend_->GetCond(c, &bool_value)) {
  402. MS_LOG(DEBUG) << "Cond:" << bool_value;
  403. if (bool_value) {
  404. Push(Ref(vtrue));
  405. } else {
  406. Push(Ref(vfalse));
  407. }
  408. } else {
  409. MS_LOG(EXCEPTION) << "Not supported type to be casted to bool";
  410. }
  411. }
  412. void FinalVM::InstSwitch(const VectorRef &args) {
  413. MS_LOG(DEBUG) << "Start";
  414. if (backend_->is_multi_graph_sink()) {
  415. InstSimuSwitch(args);
  416. } else {
  417. InstRealSwitch(args);
  418. }
  419. MS_LOG(DEBUG) << "End";
  420. }
  421. void FinalVM::InstTuple(const VectorRef &args) {
  422. MS_LOG(DEBUG) << "Start";
  423. VectorRef tuple;
  424. auto iter = args.begin();
  425. for (; iter != args.end(); ++iter) {
  426. auto a = utils::cast<int>(*iter);
  427. tuple.push_back(Ref(a));
  428. }
  429. Push(tuple);
  430. MS_LOG(DEBUG) << "End";
  431. }
  432. void FinalVM::InstPush(const VectorRef &args) {
  433. MS_LOG(DEBUG) << "Start";
  434. const size_t args_size = 1;
  435. if (args.size() != args_size) {
  436. MS_LOG(ERROR) << __FUNCTION__ << " requires " << args_size << " parameter, while the input size is " << args.size()
  437. << ".";
  438. return;
  439. }
  440. auto v = args[0];
  441. Push(v);
  442. MS_LOG(DEBUG) << "End";
  443. }
  444. void FinalVM::InstInput(const VectorRef &args) {
  445. MS_LOG(DEBUG) << "Start";
  446. const size_t args_size = 1;
  447. if (args.size() != args_size) {
  448. MS_LOG(ERROR) << __FUNCTION__ << " requires " << args_size << " parameter, while the input size is " << args.size()
  449. << ".";
  450. return;
  451. }
  452. int rpos = utils::cast<int>(args[0]);
  453. Push(Ref(rpos));
  454. MS_LOG(DEBUG) << "End";
  455. }
  456. void FinalVM::InstPadStack(const VectorRef &args) {
  457. MS_LOG(DEBUG) << "Start";
  458. const size_t args_size = 1;
  459. if (args.size() != args_size) {
  460. MS_LOG(ERROR) << __FUNCTION__ << " requires " << args_size << " parameter, while the input size is " << args.size()
  461. << ".";
  462. return;
  463. }
  464. int sz = utils::cast<int>(args[0]);
  465. MS_LOG(DEBUG) << insts_stack_.size() << " need padstack " << sz << " sp_ " << sp_;
  466. size_t stack_size = insts_stack_.size();
  467. int need = sz - (static_cast<int>(stack_size) - sp_);
  468. if (need > 0) {
  469. MS_LOG(DEBUG) << "InstPadStack resize: size:" << insts_stack_.size() << " need pad:" << need;
  470. insts_stack_.resize(stack_size + IntToSize(need));
  471. }
  472. MS_LOG(DEBUG) << "End";
  473. }
  474. void FinalVM::InstExternal(const VectorRef &args) {
  475. MS_LOG(DEBUG) << "Start:" << args.size();
  476. if (args.empty()) {
  477. MS_LOG(EXCEPTION) << "Args is empty!";
  478. }
  479. VectorRef tuple;
  480. RunFunctionRef run_ref = utils::cast<RunFunctionRef>(args[0]);
  481. compile::RunFuncPtr fn = run_ref.func_;
  482. if (backend_->simu_flag()) {
  483. MS_LOG(DEBUG) << "Simu run";
  484. if (args.size() == 1) {
  485. MS_LOG(EXCEPTION) << "The number of args should be greater than 1, but got 1";
  486. }
  487. auto simu_run_ref = utils::cast<RunFunctionRef>(args[1]);
  488. fn = simu_run_ref.func_;
  489. }
  490. for (size_t i = 2; i < args.size(); ++i) {
  491. auto index = utils::cast<int>(args[i]);
  492. tuple.push_back(Ref(index));
  493. }
  494. if (!fn) {
  495. MS_LOG(EXCEPTION) << "Function not callable";
  496. }
  497. auto outs = (*fn)(tuple);
  498. MS_LOG(DEBUG) << "'fn' out size:" << outs.size();
  499. for (auto &o : outs) {
  500. MS_LOG(DEBUG) << "InstExternal value:" << o.ToString();
  501. Push(o);
  502. }
  503. MS_LOG(DEBUG) << "End";
  504. }
  505. void FinalVM::InstPushPrim(const VectorRef &args) {
  506. MS_LOG(DEBUG) << "Start: " << args.size();
  507. const size_t args_size = 2;
  508. if (args.size() < args_size) {
  509. MS_LOG(ERROR) << __FUNCTION__ << " requires " << args_size << " or more parameters, while the input size is "
  510. << args.size() << ".";
  511. return;
  512. }
  513. VectorRef tuple;
  514. auto prim = utils::cast<PrimitivePtr>(args[0]);
  515. for (size_t i = 1; i < args.size(); ++i) {
  516. auto index = utils::cast<int>(args[1]);
  517. tuple.push_back(Ref(index));
  518. }
  519. auto outs = RunOperation(prim, tuple);
  520. Push(outs);
  521. MS_LOG(DEBUG) << "End";
  522. }
  523. } // namespace compile
  524. } // namespace mindspore