insn_to_string.rs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684
  1. // SPDX-License-Identifier: Apache-2.0
  2. use crate::lir_tests::helpers::{identifier, new_printer, new_vartable, num_literal, set_tmp};
  3. use crate::{num_literal, stringfy_insn};
  4. use num_bigint::BigInt;
  5. use solang::codegen::cfg;
  6. use solang::lir::expressions::{BinaryOperator, Expression};
  7. use solang::lir::instructions::Instruction;
  8. use solang::lir::lir_type::{InternalCallTy, PhiInput, StructType, Type};
  9. use solang::sema::ast::{ArrayLength, CallTy};
  10. use solang_parser::pt::Loc;
  11. #[test]
  12. fn test_stringfy_nop_insn() {
  13. assert_eq!(
  14. stringfy_insn!(&new_printer(&new_vartable()), &Instruction::Nop),
  15. "nop;"
  16. );
  17. }
  18. // ReturnData
  19. #[test]
  20. fn test_stringfy_returndata_insn() {
  21. let mut v = new_vartable();
  22. set_tmp(&mut v, 0, Type::Bytes(1));
  23. let printer = new_printer(&v);
  24. assert_eq!(
  25. stringfy_insn!(
  26. &printer,
  27. &Instruction::ReturnData {
  28. loc: /*missing from cfg*/ Loc::Codegen,
  29. data: identifier(0),
  30. data_len: num_literal!(1),
  31. }
  32. ),
  33. "return_data bytes1(%temp.ssa_ir.0) of length uint8(1);"
  34. );
  35. }
  36. // ReturnCode
  37. #[test]
  38. fn test_stringfy_returncode_insn() {
  39. assert_eq!(
  40. stringfy_insn!(
  41. &new_printer(&new_vartable()),
  42. &Instruction::ReturnCode {
  43. loc: /*missing from cfg*/ Loc::Codegen,
  44. code: cfg::ReturnCode::AbiEncodingInvalid,
  45. }
  46. ),
  47. "return_code \"abi encoding invalid\";"
  48. );
  49. assert_eq!(
  50. stringfy_insn!(
  51. &new_printer(&new_vartable()),
  52. &Instruction::ReturnCode {
  53. loc: /*missing from cfg*/ Loc::Codegen,
  54. code: cfg::ReturnCode::AccountDataTooSmall,
  55. }
  56. ),
  57. "return_code \"account data too small\";"
  58. );
  59. }
  60. // Set
  61. #[test]
  62. fn test_stringfy_set_insn() {
  63. let mut v = new_vartable();
  64. set_tmp(&mut v, 121, Type::Uint(8));
  65. set_tmp(&mut v, 122, Type::Uint(8));
  66. let printer = new_printer(&v);
  67. assert_eq!(
  68. stringfy_insn!(
  69. &printer,
  70. &Instruction::Set {
  71. loc: Loc::Codegen,
  72. res: 122,
  73. expr: Expression::BinaryExpr {
  74. loc: Loc::Codegen,
  75. operator: BinaryOperator::Mul { overflowing: true },
  76. left: Box::new(num_literal!(1)),
  77. right: Box::new(identifier(121))
  78. }
  79. }
  80. ),
  81. "uint8 %temp.ssa_ir.122 = uint8(1) (of)* uint8(%temp.ssa_ir.121);"
  82. );
  83. }
  84. // Store
  85. #[test]
  86. fn test_stringfy_store_insn() {
  87. let mut v = new_vartable();
  88. set_tmp(&mut v, 0, Type::Ptr(Box::new(Type::Uint(8))));
  89. set_tmp(&mut v, 1, Type::Uint(8));
  90. let printer = new_printer(&v);
  91. assert_eq!(
  92. stringfy_insn!(
  93. &printer,
  94. &Instruction::Store {
  95. loc: /*missing from cfg*/ Loc::Codegen,
  96. dest: identifier(0),
  97. data: identifier(1),
  98. }
  99. ),
  100. "store uint8(%temp.ssa_ir.1) to ptr<uint8>(%temp.ssa_ir.0);"
  101. );
  102. // store a number
  103. assert_eq!(
  104. stringfy_insn!(
  105. &printer,
  106. &Instruction::Store {
  107. loc: /*missing from cfg*/ Loc::Codegen,
  108. dest: identifier(0),
  109. data: num_literal!(1),
  110. }
  111. ),
  112. "store uint8(1) to ptr<uint8>(%temp.ssa_ir.0);"
  113. );
  114. }
  115. // PushMemory
  116. #[test]
  117. fn test_stringfy_push_memory_insn() {
  118. let mut v = new_vartable();
  119. set_tmp(
  120. &mut v,
  121. 3,
  122. Type::Ptr(Box::new(Type::Array(
  123. Box::new(Type::Uint(32)),
  124. vec![ArrayLength::Fixed(BigInt::from(3))],
  125. ))),
  126. );
  127. set_tmp(&mut v, 101, Type::Uint(32));
  128. let printer = new_printer(&v);
  129. assert_eq!(
  130. stringfy_insn!(
  131. &printer,
  132. &Instruction::PushMemory {
  133. loc: /*missing from cfg*/ Loc::Codegen,
  134. res: 101,
  135. array: 3,
  136. value: num_literal!(1, 32),
  137. }
  138. ),
  139. "uint32 %temp.ssa_ir.101 = push_mem ptr<uint32[3]>(%temp.ssa_ir.3) uint32(1);"
  140. );
  141. }
  142. #[test]
  143. fn test_stringfy_pop_memory_insn() {
  144. let mut v = new_vartable();
  145. set_tmp(
  146. &mut v,
  147. 3,
  148. Type::Ptr(Box::new(Type::Array(
  149. Box::new(Type::Uint(32)),
  150. vec![ArrayLength::Fixed(BigInt::from(3))],
  151. ))),
  152. );
  153. set_tmp(&mut v, 101, Type::Uint(32));
  154. let printer = new_printer(&v);
  155. assert_eq!(
  156. stringfy_insn!(
  157. &printer,
  158. &Instruction::PopMemory {
  159. res: 101,
  160. array: 3,
  161. loc: Loc::Codegen,
  162. }
  163. ),
  164. "uint32 %temp.ssa_ir.101 = pop_mem ptr<uint32[3]>(%temp.ssa_ir.3);"
  165. );
  166. }
  167. // LoadStorage
  168. #[test]
  169. fn test_stringfy_load_storage_insn() {
  170. let mut v = new_vartable();
  171. set_tmp(&mut v, 101, Type::Uint(32));
  172. set_tmp(&mut v, 3, Type::StoragePtr(false, Box::new(Type::Uint(32))));
  173. let printer = new_printer(&v);
  174. assert_eq!(
  175. stringfy_insn!(
  176. &printer,
  177. &Instruction::LoadStorage {
  178. loc: /*missing from cfg*/ Loc::Codegen,
  179. res: 101,
  180. storage: identifier(3)
  181. }
  182. ),
  183. "uint32 %temp.ssa_ir.101 = load_storage storage_ptr<uint32>(%temp.ssa_ir.3);"
  184. );
  185. }
  186. #[test]
  187. fn test_stringfy_clear_storage_insn() {
  188. let mut v = new_vartable();
  189. set_tmp(&mut v, 3, Type::StoragePtr(false, Box::new(Type::Uint(32))));
  190. let printer = new_printer(&v);
  191. assert_eq!(
  192. stringfy_insn!(
  193. &printer,
  194. &Instruction::ClearStorage {
  195. loc: /*missing from cfg*/ Loc::Codegen,
  196. storage: identifier(3)
  197. }
  198. ),
  199. "clear_storage storage_ptr<uint32>(%temp.ssa_ir.3);"
  200. );
  201. }
  202. #[test]
  203. fn test_stringfy_set_storage_insn() {
  204. let mut v = new_vartable();
  205. set_tmp(
  206. &mut v,
  207. 1,
  208. Type::StoragePtr(false, Box::new(Type::Uint(256))),
  209. );
  210. let printer = new_printer(&v);
  211. assert_eq!(
  212. stringfy_insn!(
  213. &printer,
  214. &Instruction::SetStorage {
  215. loc: /*missing from cfg*/ Loc::Codegen,
  216. value: num_literal(13445566, false, 256),
  217. storage: identifier(1)
  218. }
  219. ),
  220. "set_storage storage_ptr<uint256>(%temp.ssa_ir.1) uint256(13445566);"
  221. );
  222. }
  223. #[test]
  224. fn test_stringfy_set_storage_bytes_insn() {
  225. let mut v = new_vartable();
  226. set_tmp(&mut v, 1, Type::Bytes(32));
  227. set_tmp(
  228. &mut v,
  229. 2,
  230. Type::StoragePtr(false, Box::new(Type::Bytes(32))),
  231. );
  232. let printer = new_printer(&v);
  233. assert_eq!(
  234. stringfy_insn!(
  235. &printer,
  236. &Instruction::SetStorageBytes {
  237. loc: /*missing from cfg*/ Loc::Codegen,
  238. value: identifier(1),
  239. storage: identifier(2),
  240. offset: num_literal!(3)
  241. }
  242. ),
  243. "set_storage_bytes storage_ptr<bytes32>(%temp.ssa_ir.2) offset:uint8(3) value:bytes32(%temp.ssa_ir.1);"
  244. );
  245. }
  246. #[test]
  247. fn test_stringfy_push_storage_insn() {
  248. let mut v = new_vartable();
  249. set_tmp(&mut v, 101, Type::Uint(32));
  250. set_tmp(
  251. &mut v,
  252. 3,
  253. Type::StoragePtr(
  254. false,
  255. Box::new(Type::Array(
  256. Box::new(Type::Uint(32)),
  257. vec![ArrayLength::Fixed(BigInt::from(3))],
  258. )),
  259. ),
  260. );
  261. let printer = new_printer(&v);
  262. assert_eq!(
  263. stringfy_insn!(
  264. &printer,
  265. &Instruction::PushStorage {
  266. loc: /*missing from cfg*/ Loc::Codegen,
  267. res: 101,
  268. value: Some(num_literal!(1, 32)),
  269. storage: identifier(3)
  270. }
  271. ),
  272. "uint32 %temp.ssa_ir.101 = push_storage storage_ptr<uint32[3]>(%temp.ssa_ir.3) uint32(1);"
  273. );
  274. }
  275. #[test]
  276. fn test_stringfy_pop_storage_insn() {
  277. let mut v = new_vartable();
  278. set_tmp(&mut v, 123, Type::Uint(32));
  279. set_tmp(
  280. &mut v,
  281. 3,
  282. Type::StoragePtr(
  283. false,
  284. Box::new(Type::Array(
  285. Box::new(Type::Uint(32)),
  286. vec![ArrayLength::Fixed(BigInt::from(3))],
  287. )),
  288. ),
  289. );
  290. let printer = new_printer(&v);
  291. assert_eq!(
  292. stringfy_insn!(
  293. &printer,
  294. &Instruction::PopStorage {
  295. loc: /*missing from cfg*/ Loc::Codegen,
  296. res: Some(123),
  297. storage: identifier(3)
  298. }
  299. ),
  300. "uint32 %temp.ssa_ir.123 = pop_storage storage_ptr<uint32[3]>(%temp.ssa_ir.3);"
  301. );
  302. assert_eq!(
  303. stringfy_insn!(
  304. &printer,
  305. &Instruction::PopStorage {
  306. loc: /*missing from cfg*/ Loc::Codegen,
  307. res: None,
  308. storage: identifier(3)
  309. }
  310. ),
  311. "pop_storage storage_ptr<uint32[3]>(%temp.ssa_ir.3);"
  312. )
  313. }
  314. #[test]
  315. fn test_stringfy_call_insn() {
  316. let mut v = new_vartable();
  317. set_tmp(&mut v, 1, Type::Uint(8));
  318. set_tmp(&mut v, 2, Type::Uint(64));
  319. set_tmp(&mut v, 3, Type::Uint(8));
  320. set_tmp(&mut v, 133, Type::Uint(64));
  321. set_tmp(
  322. &mut v,
  323. 123,
  324. Type::Ptr(Box::new(Type::Function {
  325. params: vec![Type::Uint(8), Type::Uint(64), Type::Uint(64)],
  326. returns: vec![Type::Uint(8), Type::Uint(64), Type::Uint(8)],
  327. })),
  328. );
  329. let printer = new_printer(&v);
  330. assert_eq!(
  331. stringfy_insn!(
  332. &printer,
  333. &Instruction::Call {
  334. loc: /*missing from cfg*/ Loc::Codegen,
  335. res: vec![1, 2, 3],
  336. call: InternalCallTy::Builtin { ast_func_no: 123 },
  337. args: vec![num_literal!(3), identifier(133), num_literal!(6, 64)],
  338. }
  339. ),
  340. "uint8 %temp.ssa_ir.1, uint64 %temp.ssa_ir.2, uint8 %temp.ssa_ir.3 = call builtin#123(uint8(3), uint64(%temp.ssa_ir.133), uint64(6));"
  341. );
  342. assert_eq!(
  343. stringfy_insn!(
  344. &printer,
  345. &Instruction::Call {
  346. loc: /*missing from cfg*/ Loc::Codegen,
  347. res: vec![1, 2, 3],
  348. call: InternalCallTy::Dynamic(identifier(123)),
  349. args: vec![num_literal!(3), identifier(133), num_literal!(6, 64)],
  350. }
  351. ),
  352. "uint8 %temp.ssa_ir.1, uint64 %temp.ssa_ir.2, uint8 %temp.ssa_ir.3 = call ptr<function (uint8, uint64, uint64) returns (uint8, uint64, uint8)>(%temp.ssa_ir.123)(uint8(3), uint64(%temp.ssa_ir.133), uint64(6));"
  353. );
  354. assert_eq!(
  355. stringfy_insn!(
  356. &printer,
  357. &Instruction::Call {
  358. loc: /*missing from cfg*/ Loc::Codegen,
  359. res: vec![1, 2, 3],
  360. call: InternalCallTy::Static { cfg_no: 123 },
  361. args: vec![num_literal!(3), identifier(133), num_literal!(6, 64)],
  362. }
  363. ),
  364. "uint8 %temp.ssa_ir.1, uint64 %temp.ssa_ir.2, uint8 %temp.ssa_ir.3 = call function#123(uint8(3), uint64(%temp.ssa_ir.133), uint64(6));"
  365. );
  366. }
  367. // ExternalCall
  368. #[test]
  369. fn test_stringfy_external_call_insn() {
  370. let mut v = new_vartable();
  371. // success
  372. set_tmp(&mut v, 1, Type::Bool);
  373. // payload
  374. set_tmp(&mut v, 3, Type::Bytes(32));
  375. // value
  376. set_tmp(&mut v, 4, Type::Uint(64));
  377. // gas
  378. set_tmp(&mut v, 7, Type::Uint(64));
  379. let printer = new_printer(&v);
  380. assert_eq!(
  381. stringfy_insn!(
  382. &printer,
  383. &Instruction::ExternalCall {
  384. success: Some(1),
  385. address: None,
  386. payload: identifier(3),
  387. value: identifier(4),
  388. accounts: solang::sema::ast::ExternalCallAccounts::AbsentArgument,
  389. seeds: None,
  390. gas: identifier(7),
  391. callty: CallTy::Regular,
  392. contract_function_no: None,
  393. flags: None,
  394. loc: Loc::Codegen,
  395. }
  396. ),
  397. "bool %temp.ssa_ir.1 = call_ext [regular] address:_ payload:bytes32(%temp.ssa_ir.3) value:uint64(%temp.ssa_ir.4) gas:uint64(%temp.ssa_ir.7) accounts:absent seeds:_ contract_no:_, function_no:_ flags:_;"
  398. );
  399. }
  400. #[test]
  401. fn test_stringfy_print_insn() {
  402. let mut v = new_vartable();
  403. set_tmp(&mut v, 3, Type::Uint(8));
  404. let printer = new_printer(&v);
  405. assert_eq!(
  406. stringfy_insn!(
  407. &printer,
  408. &Instruction::Print {
  409. loc: /*missing from cfg*/ Loc::Codegen,
  410. operand: identifier(3)
  411. }
  412. ),
  413. "print uint8(%temp.ssa_ir.3);"
  414. );
  415. }
  416. #[test]
  417. fn test_stringfy_memcopy_insn() {
  418. let mut v = new_vartable();
  419. set_tmp(&mut v, 3, Type::Bytes(32));
  420. set_tmp(&mut v, 4, Type::Bytes(16));
  421. let printer = new_printer(&v);
  422. assert_eq!(
  423. stringfy_insn!(
  424. &printer,
  425. &Instruction::MemCopy {
  426. loc: /*missing from cfg*/ Loc::Codegen,
  427. src: identifier(3),
  428. dest: identifier(4),
  429. bytes: num_literal!(16)
  430. }
  431. ),
  432. "memcopy bytes32(%temp.ssa_ir.3) to bytes16(%temp.ssa_ir.4) for uint8(16) bytes;"
  433. )
  434. }
  435. #[test]
  436. fn test_stringfy_value_transfer_insn() {
  437. let mut v = new_vartable();
  438. set_tmp(&mut v, 1, Type::Bool);
  439. set_tmp(
  440. &mut v,
  441. 2,
  442. Type::Array(
  443. Box::new(Type::Uint(8)),
  444. vec![ArrayLength::Fixed(BigInt::from(32))],
  445. ),
  446. );
  447. set_tmp(&mut v, 3, Type::Uint(8));
  448. let printer = new_printer(&v);
  449. assert_eq!(
  450. stringfy_insn!(
  451. &printer,
  452. &Instruction::ValueTransfer {
  453. loc: /*missing from cfg*/ Loc::Codegen,
  454. success: Some(1),
  455. address: identifier(2),
  456. value: identifier(3),
  457. }
  458. ),
  459. "bool %temp.ssa_ir.1 = value_transfer uint8(%temp.ssa_ir.3) to uint8[32](%temp.ssa_ir.2);"
  460. );
  461. }
  462. #[test]
  463. fn test_stringfy_selfdestruct_insn() {
  464. let mut v = new_vartable();
  465. set_tmp(
  466. &mut v,
  467. 3,
  468. Type::Ptr(Box::new(Type::Struct(StructType::UserDefined(0)))),
  469. );
  470. let printer = new_printer(&v);
  471. assert_eq!(
  472. stringfy_insn!(
  473. &printer,
  474. &Instruction::SelfDestruct {
  475. loc: /*missing from cfg*/ Loc::Codegen,
  476. recipient: identifier(3)
  477. }
  478. ),
  479. "self_destruct ptr<struct.0>(%temp.ssa_ir.3);"
  480. )
  481. }
  482. #[test]
  483. fn test_stringfy_emit_event_insn() {
  484. let mut v = new_vartable();
  485. set_tmp(&mut v, 1, Type::Bytes(32));
  486. set_tmp(&mut v, 2, Type::Bytes(32));
  487. set_tmp(&mut v, 3, Type::Bytes(32));
  488. let printer = new_printer(&v);
  489. assert_eq!(
  490. stringfy_insn!(
  491. &printer,
  492. &Instruction::EmitEvent {
  493. loc: /*missing from cfg*/ Loc::Codegen,
  494. event_no: 13,
  495. topics: vec![identifier(1), identifier(2)],
  496. data: identifier(3)
  497. }
  498. ),
  499. "emit event#13 to topics[bytes32(%temp.ssa_ir.1), bytes32(%temp.ssa_ir.2)], data: bytes32(%temp.ssa_ir.3);"
  500. )
  501. }
  502. #[test]
  503. fn test_stringfy_branch_insn() {
  504. assert_eq!(
  505. stringfy_insn!(
  506. &new_printer(&new_vartable()),
  507. &Instruction::Branch {
  508. loc: /*missing from cfg*/ Loc::Codegen,
  509. block: 3
  510. }
  511. ),
  512. "br block#3;"
  513. )
  514. }
  515. #[test]
  516. fn test_stringfy_branch_cond_insn() {
  517. let mut v = new_vartable();
  518. set_tmp(&mut v, 3, Type::Bool);
  519. let printer = new_printer(&v);
  520. assert_eq!(
  521. stringfy_insn!(
  522. &printer,
  523. &Instruction::BranchCond {
  524. loc: /*missing from cfg*/ Loc::Codegen,
  525. cond: identifier(3),
  526. true_block: 5,
  527. false_block: 6
  528. }
  529. ),
  530. "cbr bool(%temp.ssa_ir.3) block#5 else block#6;"
  531. )
  532. }
  533. #[test]
  534. fn test_stringfy_switch_insn() {
  535. let mut v = new_vartable();
  536. set_tmp(&mut v, 1, Type::Uint(8));
  537. set_tmp(&mut v, 4, Type::Uint(8));
  538. set_tmp(&mut v, 5, Type::Uint(8));
  539. set_tmp(&mut v, 6, Type::Uint(8));
  540. let printer = new_printer(&v);
  541. let s = stringfy_insn!(
  542. &printer,
  543. &Instruction::Switch {
  544. loc: /*missing from cfg*/ Loc::Codegen,
  545. cond: identifier(1),
  546. cases: vec![
  547. (identifier(4), 11),
  548. (identifier(5), 12),
  549. (identifier(6), 13),
  550. ],
  551. default: 14,
  552. }
  553. );
  554. assert_eq!(
  555. s,
  556. r#"switch uint8(%temp.ssa_ir.1):
  557. case: uint8(%temp.ssa_ir.4) => block#11,
  558. case: uint8(%temp.ssa_ir.5) => block#12,
  559. case: uint8(%temp.ssa_ir.6) => block#13
  560. default: block#14;"#
  561. )
  562. }
  563. #[test]
  564. fn test_stringfy_return_insn() {
  565. let mut v = new_vartable();
  566. set_tmp(&mut v, 1, Type::Uint(8));
  567. set_tmp(&mut v, 2, Type::Bytes(32));
  568. let printer = new_printer(&v);
  569. assert_eq!(
  570. stringfy_insn!(
  571. &printer,
  572. &Instruction::Return {
  573. loc: /*missing from cfg*/ Loc::Codegen,
  574. value: vec![identifier(1), identifier(2)]
  575. }
  576. ),
  577. "return uint8(%temp.ssa_ir.1), bytes32(%temp.ssa_ir.2);"
  578. )
  579. }
  580. #[test]
  581. fn test_stringfy_assert_failure_insn() {
  582. let mut v = new_vartable();
  583. set_tmp(&mut v, 3, Type::Bytes(32));
  584. let printer = new_printer(&v);
  585. assert_eq!(
  586. stringfy_insn!(
  587. &printer,
  588. &Instruction::AssertFailure {
  589. loc: /*missing from cfg*/ Loc::Codegen,
  590. encoded_args: Some(identifier(3))
  591. }
  592. ),
  593. "assert_failure bytes32(%temp.ssa_ir.3);"
  594. );
  595. assert_eq!(
  596. stringfy_insn!(
  597. &new_printer(&new_vartable()),
  598. &Instruction::AssertFailure {
  599. loc: /*missing from cfg*/ Loc::Codegen,
  600. encoded_args: None
  601. }
  602. ),
  603. "assert_failure;"
  604. )
  605. }
  606. #[test]
  607. fn test_stringfy_phi_insn() {
  608. let mut v = new_vartable();
  609. set_tmp(&mut v, 1, Type::Uint(8));
  610. set_tmp(&mut v, 2, Type::Uint(8));
  611. set_tmp(&mut v, 12, Type::Uint(8));
  612. let printer = new_printer(&v);
  613. assert_eq!(
  614. stringfy_insn!(
  615. &printer,
  616. &Instruction::Phi {
  617. loc: /*missing from cfg*/ Loc::Codegen,
  618. res: 12,
  619. vars: vec![
  620. PhiInput::new(identifier(1), 13),
  621. PhiInput::new(identifier(2), 14)
  622. ],
  623. }
  624. ),
  625. "uint8 %temp.ssa_ir.12 = phi [uint8(%temp.ssa_ir.1), block#13], [uint8(%temp.ssa_ir.2), block#14];"
  626. )
  627. }