expr_to_string.rs 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156
  1. // SPDX-License-Identifier: Apache-2.0
  2. use crate::lir_tests::helpers::{
  3. binop_expr, bool_literal, identifier, new_lir_type, new_printer, new_vartable, num_literal,
  4. set_tmp, unop_expr,
  5. };
  6. use crate::num_literal;
  7. use crate::stringfy_expr;
  8. use num_bigint::BigInt;
  9. use solang::codegen::Builtin;
  10. use solang::lir::expressions::{BinaryOperator, Expression, UnaryOperator};
  11. use solang::lir::lir_type::{StructType, Type};
  12. use solang::sema::ast::{self, ArrayLength, FormatArg, StringLocation};
  13. use solang_parser::pt::Loc;
  14. #[test]
  15. fn test_stringfy_binary_expr() {
  16. let mut v = new_vartable();
  17. for i in 0..100 {
  18. set_tmp(&mut v, i, Type::Int(16));
  19. }
  20. let printer = new_printer(&v);
  21. assert_eq!(
  22. stringfy_expr!(
  23. &printer,
  24. &binop_expr(
  25. identifier(1),
  26. BinaryOperator::Add { overflowing: false },
  27. identifier(2)
  28. )
  29. ),
  30. "int16(%temp.ssa_ir.1) + int16(%temp.ssa_ir.2)"
  31. );
  32. assert_eq!(
  33. stringfy_expr!(
  34. &printer,
  35. &binop_expr(
  36. identifier(1),
  37. BinaryOperator::Add { overflowing: true },
  38. identifier(2)
  39. )
  40. ),
  41. "int16(%temp.ssa_ir.1) (of)+ int16(%temp.ssa_ir.2)"
  42. );
  43. // Sub { overflowing: bool },
  44. assert_eq!(
  45. stringfy_expr!(
  46. &printer,
  47. &binop_expr(
  48. identifier(11),
  49. BinaryOperator::Sub { overflowing: false },
  50. identifier(12)
  51. )
  52. ),
  53. "int16(%temp.ssa_ir.11) - int16(%temp.ssa_ir.12)"
  54. );
  55. assert_eq!(
  56. stringfy_expr!(
  57. &printer,
  58. &binop_expr(
  59. identifier(12),
  60. BinaryOperator::Sub { overflowing: true },
  61. identifier(13)
  62. )
  63. ),
  64. "int16(%temp.ssa_ir.12) (of)- int16(%temp.ssa_ir.13)"
  65. );
  66. // Mul { overflowing: bool },
  67. assert_eq!(
  68. stringfy_expr!(
  69. &printer,
  70. &binop_expr(
  71. identifier(13),
  72. BinaryOperator::Mul { overflowing: false },
  73. identifier(14)
  74. )
  75. ),
  76. "int16(%temp.ssa_ir.13) * int16(%temp.ssa_ir.14)"
  77. );
  78. assert_eq!(
  79. stringfy_expr!(
  80. &printer,
  81. &binop_expr(
  82. identifier(1),
  83. BinaryOperator::Mul { overflowing: true },
  84. identifier(9)
  85. )
  86. ),
  87. "int16(%temp.ssa_ir.1) (of)* int16(%temp.ssa_ir.9)"
  88. );
  89. // Pow { overflowing: bool },
  90. assert_eq!(
  91. stringfy_expr!(
  92. &printer,
  93. &binop_expr(
  94. identifier(10),
  95. BinaryOperator::Pow { overflowing: true },
  96. identifier(11)
  97. )
  98. ),
  99. "int16(%temp.ssa_ir.10) (of)** int16(%temp.ssa_ir.11)"
  100. );
  101. // Div,
  102. assert_eq!(
  103. stringfy_expr!(
  104. &printer,
  105. &binop_expr(identifier(1), BinaryOperator::Div, identifier(2))
  106. ),
  107. "int16(%temp.ssa_ir.1) / int16(%temp.ssa_ir.2)"
  108. );
  109. // UDiv,
  110. assert_eq!(
  111. stringfy_expr!(
  112. &printer,
  113. &binop_expr(identifier(3), BinaryOperator::UDiv, identifier(4))
  114. ),
  115. "int16(%temp.ssa_ir.3) (u)/ int16(%temp.ssa_ir.4)"
  116. );
  117. // Mod,
  118. assert_eq!(
  119. stringfy_expr!(
  120. &printer,
  121. &binop_expr(identifier(4), BinaryOperator::Mod, identifier(5))
  122. ),
  123. "int16(%temp.ssa_ir.4) % int16(%temp.ssa_ir.5)"
  124. );
  125. // UMod,
  126. assert_eq!(
  127. stringfy_expr!(
  128. &printer,
  129. &binop_expr(identifier(2), BinaryOperator::UMod, identifier(3))
  130. ),
  131. "int16(%temp.ssa_ir.2) (u)% int16(%temp.ssa_ir.3)"
  132. );
  133. // Eq,
  134. assert_eq!(
  135. stringfy_expr!(
  136. &printer,
  137. &binop_expr(identifier(2), BinaryOperator::Eq, identifier(4))
  138. ),
  139. "int16(%temp.ssa_ir.2) == int16(%temp.ssa_ir.4)"
  140. );
  141. // Neq,
  142. assert_eq!(
  143. stringfy_expr!(
  144. &printer,
  145. &binop_expr(identifier(2), BinaryOperator::Neq, identifier(3))
  146. ),
  147. "int16(%temp.ssa_ir.2) != int16(%temp.ssa_ir.3)"
  148. );
  149. // Lt,
  150. assert_eq!(
  151. stringfy_expr!(
  152. &printer,
  153. &binop_expr(identifier(1), BinaryOperator::Lt, identifier(2))
  154. ),
  155. "int16(%temp.ssa_ir.1) < int16(%temp.ssa_ir.2)"
  156. );
  157. // ULt,
  158. assert_eq!(
  159. stringfy_expr!(
  160. &printer,
  161. &binop_expr(identifier(1), BinaryOperator::ULt, identifier(0))
  162. ),
  163. "int16(%temp.ssa_ir.1) (u)< int16(%temp.ssa_ir.0)"
  164. );
  165. // Lte,
  166. assert_eq!(
  167. stringfy_expr!(
  168. &printer,
  169. &binop_expr(identifier(1), BinaryOperator::Lte, identifier(2))
  170. ),
  171. "int16(%temp.ssa_ir.1) <= int16(%temp.ssa_ir.2)"
  172. );
  173. // ULte,
  174. assert_eq!(
  175. stringfy_expr!(
  176. &printer,
  177. &binop_expr(identifier(1), BinaryOperator::ULte, identifier(2))
  178. ),
  179. "int16(%temp.ssa_ir.1) (u)<= int16(%temp.ssa_ir.2)"
  180. );
  181. // Gt,
  182. assert_eq!(
  183. stringfy_expr!(
  184. &printer,
  185. &binop_expr(identifier(1), BinaryOperator::Gt, identifier(2))
  186. ),
  187. "int16(%temp.ssa_ir.1) > int16(%temp.ssa_ir.2)"
  188. );
  189. // UGt,
  190. assert_eq!(
  191. stringfy_expr!(
  192. &printer,
  193. &binop_expr(identifier(1), BinaryOperator::UGt, identifier(2))
  194. ),
  195. "int16(%temp.ssa_ir.1) (u)> int16(%temp.ssa_ir.2)"
  196. );
  197. // Gte,
  198. assert_eq!(
  199. stringfy_expr!(
  200. &printer,
  201. &binop_expr(identifier(1), BinaryOperator::Gte, identifier(2))
  202. ),
  203. "int16(%temp.ssa_ir.1) >= int16(%temp.ssa_ir.2)"
  204. );
  205. // UGte,
  206. assert_eq!(
  207. stringfy_expr!(
  208. &printer,
  209. &binop_expr(identifier(1), BinaryOperator::UGte, identifier(2))
  210. ),
  211. "int16(%temp.ssa_ir.1) (u)>= int16(%temp.ssa_ir.2)"
  212. );
  213. // BitAnd,
  214. assert_eq!(
  215. stringfy_expr!(
  216. &printer,
  217. &binop_expr(
  218. bool_literal(false),
  219. BinaryOperator::BitAnd,
  220. bool_literal(true)
  221. )
  222. ),
  223. "false & true"
  224. );
  225. // BitOr,
  226. assert_eq!(
  227. stringfy_expr!(
  228. &printer,
  229. &binop_expr(identifier(3), BinaryOperator::BitOr, identifier(4))
  230. ),
  231. "int16(%temp.ssa_ir.3) | int16(%temp.ssa_ir.4)"
  232. );
  233. // BitXor,
  234. assert_eq!(
  235. stringfy_expr!(
  236. &printer,
  237. &binop_expr(identifier(1), BinaryOperator::BitXor, identifier(2))
  238. ),
  239. "int16(%temp.ssa_ir.1) ^ int16(%temp.ssa_ir.2)"
  240. );
  241. // Shl,
  242. assert_eq!(
  243. stringfy_expr!(
  244. &printer,
  245. &binop_expr(identifier(3), BinaryOperator::Shl, identifier(4))
  246. ),
  247. "int16(%temp.ssa_ir.3) << int16(%temp.ssa_ir.4)"
  248. );
  249. // Shr,
  250. assert_eq!(
  251. stringfy_expr!(
  252. &printer,
  253. &binop_expr(identifier(3), BinaryOperator::Shr, identifier(4))
  254. ),
  255. "int16(%temp.ssa_ir.3) >> int16(%temp.ssa_ir.4)"
  256. );
  257. // UShr,
  258. assert_eq!(
  259. stringfy_expr!(
  260. &printer,
  261. &binop_expr(identifier(3), BinaryOperator::UShr, identifier(4))
  262. ),
  263. "int16(%temp.ssa_ir.3) (u)>> int16(%temp.ssa_ir.4)"
  264. );
  265. }
  266. #[test]
  267. fn test_stringfy_unary_expr() {
  268. let mut v = new_vartable();
  269. set_tmp(&mut v, 1, Type::Int(16));
  270. set_tmp(&mut v, 2, Type::Int(16));
  271. set_tmp(&mut v, 4, Type::Int(16));
  272. let printer = new_printer(&v);
  273. // Not,
  274. assert_eq!(
  275. stringfy_expr!(
  276. new_printer(&new_vartable()),
  277. &unop_expr(UnaryOperator::Not, bool_literal(true))
  278. ),
  279. "!true"
  280. );
  281. // Neg { overflowing: bool },
  282. assert_eq!(
  283. stringfy_expr!(
  284. &printer,
  285. &unop_expr(UnaryOperator::Neg { overflowing: false }, identifier(1))
  286. ),
  287. "-int16(%temp.ssa_ir.1)"
  288. );
  289. assert_eq!(
  290. stringfy_expr!(
  291. &printer,
  292. &unop_expr(UnaryOperator::Neg { overflowing: true }, identifier(2))
  293. ),
  294. "(of)-int16(%temp.ssa_ir.2)"
  295. );
  296. // BitNot,
  297. assert_eq!(
  298. stringfy_expr!(&printer, &unop_expr(UnaryOperator::BitNot, identifier(4))),
  299. "~int16(%temp.ssa_ir.4)"
  300. );
  301. }
  302. #[test]
  303. fn test_stringfy_id_expr() {
  304. let mut v = new_vartable();
  305. set_tmp(&mut v, 1, Type::Int(16));
  306. let printer = new_printer(&v);
  307. assert_eq!(
  308. stringfy_expr!(
  309. &printer,
  310. &Expression::Id {
  311. loc: Loc::Codegen,
  312. id: 1,
  313. }
  314. ),
  315. "int16(%temp.ssa_ir.1)"
  316. );
  317. }
  318. #[test]
  319. fn test_stringfy_array_literal_expr() {
  320. // let printer = new_printer();
  321. let vartab = &new_vartable();
  322. let printer = new_printer(vartab);
  323. assert_eq!(
  324. stringfy_expr!(
  325. &printer,
  326. &Expression::ArrayLiteral {
  327. loc: Loc::Codegen,
  328. ty: new_lir_type(Type::Array(
  329. Box::new(Type::Bool),
  330. vec![ast::ArrayLength::Fixed(BigInt::from(2))]
  331. )),
  332. dimensions: vec![2],
  333. values: vec![bool_literal(true), bool_literal(false)],
  334. }
  335. ),
  336. "bool[2] [true, false]"
  337. );
  338. // int array
  339. assert_eq!(
  340. stringfy_expr!(
  341. &printer,
  342. &Expression::ArrayLiteral {
  343. loc: Loc::Codegen,
  344. ty: new_lir_type(Type::Array(
  345. Box::new(Type::Int(8)),
  346. vec![ast::ArrayLength::Fixed(BigInt::from(2))]
  347. )),
  348. dimensions: vec![2],
  349. values: vec![num_literal(1, true, 8), num_literal(2, true, 8)],
  350. }
  351. ),
  352. "int8[2] [int8(1), int8(2)]"
  353. );
  354. // uint array
  355. assert_eq!(
  356. stringfy_expr!(
  357. &printer,
  358. &Expression::ArrayLiteral {
  359. loc: Loc::Codegen,
  360. ty: new_lir_type(Type::Array(
  361. Box::new(Type::Uint(8)),
  362. vec![ast::ArrayLength::Fixed(BigInt::from(2))]
  363. )),
  364. dimensions: vec![2],
  365. values: vec![num_literal!(1), num_literal!(2)],
  366. }
  367. ),
  368. "uint8[2] [uint8(1), uint8(2)]"
  369. );
  370. // 2d int array
  371. assert_eq!(
  372. stringfy_expr!(
  373. &printer,
  374. &Expression::ArrayLiteral {
  375. loc: Loc::Codegen,
  376. ty: new_lir_type(Type::Array(
  377. Box::new(Type::Int(8)),
  378. vec![
  379. ast::ArrayLength::Fixed(BigInt::from(2)),
  380. ast::ArrayLength::Fixed(BigInt::from(2))
  381. ]
  382. )),
  383. dimensions: vec![2, 2],
  384. values: vec![
  385. num_literal(1, true, 8),
  386. num_literal(2, true, 8),
  387. num_literal(3, true, 8),
  388. num_literal(4, true, 8)
  389. ],
  390. }
  391. ),
  392. "int8[2][2] [int8(1), int8(2), int8(3), int8(4)]"
  393. );
  394. // 3d int array
  395. // for example: int8[2][2][2] = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]
  396. assert_eq!(
  397. stringfy_expr!(
  398. &printer,
  399. &Expression::ArrayLiteral {
  400. loc: Loc::Codegen,
  401. ty: new_lir_type(Type::Array(
  402. Box::new(Type::Int(8)),
  403. vec![
  404. ast::ArrayLength::Fixed(BigInt::from(2)),
  405. ast::ArrayLength::Fixed(BigInt::from(2)),
  406. ast::ArrayLength::Fixed(BigInt::from(2))
  407. ]
  408. )),
  409. dimensions: vec![2, 2, 2],
  410. values: vec![
  411. num_literal(1, true, 8),
  412. num_literal(2, true, 8),
  413. num_literal(3, true, 8),
  414. num_literal(4, true, 8),
  415. num_literal(5, true, 8),
  416. num_literal(6, true, 8),
  417. num_literal(7, true, 8),
  418. num_literal(8, true, 8)
  419. ],
  420. }
  421. ),
  422. "int8[2][2][2] [int8(1), int8(2), int8(3), int8(4), int8(5), int8(6), int8(7), int8(8)]"
  423. );
  424. assert_eq!(
  425. stringfy_expr!(&printer, &Expression::ConstArrayLiteral {
  426. loc: Loc::Codegen,
  427. ty: new_lir_type(Type::Array(
  428. Box::new(Type::Int(8)),
  429. vec![
  430. ast::ArrayLength::Fixed(BigInt::from(2)),
  431. ast::ArrayLength::Fixed(BigInt::from(2)),
  432. ast::ArrayLength::Fixed(BigInt::from(2))
  433. ]
  434. )),
  435. dimensions: vec![2, 2, 2],
  436. values: vec![
  437. num_literal(1, true, 8),
  438. num_literal(2, true, 8),
  439. num_literal(3, true, 8),
  440. num_literal(4, true, 8),
  441. num_literal(5, true, 8),
  442. num_literal(6, true, 8),
  443. num_literal(7, true, 8),
  444. num_literal(8, true, 8)
  445. ],
  446. }
  447. ),
  448. "const int8[2][2][2] [int8(1), int8(2), int8(3), int8(4), int8(5), int8(6), int8(7), int8(8)]"
  449. );
  450. }
  451. #[test]
  452. fn test_stringfy_bytes_literal_expr() {
  453. // example: bytes4 hex"41_42_43_44";
  454. assert_eq!(
  455. stringfy_expr!(
  456. &new_printer(&new_vartable()),
  457. &Expression::BytesLiteral {
  458. loc: Loc::Codegen,
  459. ty: new_lir_type(Type::Bytes(4)),
  460. value: vec![0x41, 0x42, 0x43, 0x44],
  461. }
  462. ),
  463. "bytes4 hex\"41_42_43_44\""
  464. );
  465. }
  466. #[test]
  467. fn test_stringfy_struct_literal_expr() {
  468. /*
  469. example:
  470. struct S {
  471. uint x;
  472. uint y;
  473. }
  474. the literal: S(1, 2)
  475. print: struct { uint8(1), uint8(2) }
  476. */
  477. assert_eq!(
  478. stringfy_expr!(
  479. &new_printer(&new_vartable()),
  480. &Expression::StructLiteral {
  481. loc: Loc::Codegen,
  482. ty: new_lir_type(Type::Struct(StructType::UserDefined(0))),
  483. values: vec![num_literal!(1, 8), num_literal!(2, 8)],
  484. }
  485. ),
  486. "struct { uint8(1), uint8(2) }"
  487. );
  488. assert_eq!(
  489. stringfy_expr!(
  490. &new_printer(&new_vartable()),
  491. &Expression::StructLiteral {
  492. loc: Loc::Codegen,
  493. ty: new_lir_type(Type::Struct(StructType::UserDefined(0))),
  494. values: vec![num_literal!(1, 8), bool_literal(false)],
  495. }
  496. ),
  497. "struct { uint8(1), false }"
  498. );
  499. }
  500. #[test]
  501. fn test_stringfy_cast_expr() {
  502. let mut v = new_vartable();
  503. set_tmp(&mut v, 1, Type::Uint(8));
  504. let printer = new_printer(&v);
  505. // example: uint8(1)
  506. assert_eq!(
  507. stringfy_expr!(
  508. &printer,
  509. &Expression::Cast {
  510. loc: Loc::Codegen,
  511. operand: Box::new(identifier(1)),
  512. to_ty: new_lir_type(Type::Uint(16)),
  513. }
  514. ),
  515. "(cast uint8(%temp.ssa_ir.1) to uint16)"
  516. );
  517. }
  518. #[test]
  519. fn test_stringfy_bytes_cast_expr() {
  520. let mut v = new_vartable();
  521. set_tmp(&mut v, 1, Type::Bytes(2));
  522. let printer = new_printer(&v);
  523. assert_eq!(
  524. stringfy_expr!(
  525. &printer,
  526. &Expression::BytesCast {
  527. loc: Loc::Codegen,
  528. operand: Box::new(identifier(1)),
  529. to_ty: new_lir_type(Type::Bytes(4)),
  530. }
  531. ),
  532. "(cast bytes2(%temp.ssa_ir.1) to bytes4)"
  533. );
  534. }
  535. #[test]
  536. fn test_stringfy_sext_expr() {
  537. let mut v = new_vartable();
  538. set_tmp(&mut v, 1, Type::Int(8));
  539. let printer = new_printer(&v);
  540. // example: sign extending a int8 to int16:
  541. // %1 of int8 to int16
  542. // can be written as: (sext %1 to int16)
  543. assert_eq!(
  544. stringfy_expr!(
  545. &printer,
  546. &Expression::SignExt {
  547. loc: Loc::Codegen,
  548. operand: Box::new(identifier(1)),
  549. to_ty: new_lir_type(Type::Int(16)),
  550. }
  551. ),
  552. "(sext int8(%temp.ssa_ir.1) to int16)"
  553. );
  554. }
  555. #[test]
  556. fn test_stringfy_zext_expr() {
  557. let mut v = new_vartable();
  558. set_tmp(&mut v, 1, Type::Uint(8));
  559. let printer = new_printer(&v);
  560. // example: zero extending a uint8 to uint16:
  561. // %1 of uint8 to uint16
  562. // can be written as: (zext %1 to int16)
  563. assert_eq!(
  564. stringfy_expr!(
  565. &printer,
  566. &Expression::ZeroExt {
  567. loc: Loc::Codegen,
  568. operand: Box::new(identifier(1)),
  569. to_ty: new_lir_type(Type::Uint(16)),
  570. }
  571. ),
  572. "(zext uint8(%temp.ssa_ir.1) to uint16)"
  573. );
  574. }
  575. #[test]
  576. fn test_stringfy_trunc_expr() {
  577. let mut v = new_vartable();
  578. set_tmp(&mut v, 1, Type::Uint(16));
  579. let printer = new_printer(&v);
  580. // example: truncating a uint16 to uint8:
  581. // %1 of uint16 to uint8
  582. // can be written as: (trunc uint16 %1 to uint8)
  583. assert_eq!(
  584. stringfy_expr!(
  585. &printer,
  586. &Expression::Trunc {
  587. loc: Loc::Codegen,
  588. operand: Box::new(identifier(1)),
  589. to_ty: new_lir_type(Type::Uint(8)),
  590. }
  591. ),
  592. "(trunc uint16(%temp.ssa_ir.1) to uint8)"
  593. );
  594. }
  595. #[test]
  596. fn test_stringfy_alloc_dyn_bytes() {
  597. // case1: allocating a dynamic bytes without initializer:
  598. // Solidity: bytes memory a = new bytes(10);
  599. // rhs print: alloc bytes1[10]
  600. assert_eq!(
  601. stringfy_expr!(
  602. &new_printer(&new_vartable()),
  603. &Expression::AllocDynamicBytes {
  604. loc: Loc::Codegen,
  605. ty: new_lir_type(Type::Bytes(1)),
  606. size: Box::new(num_literal!(10)),
  607. initializer: None,
  608. }
  609. ),
  610. "alloc bytes1[uint8(10)]"
  611. );
  612. // case2: allocating a dynamic bytes with initializer:
  613. // Solidity: bytes memory a = new bytes(3) { 0x01, 0x02, 0x03 };
  614. // rhs print: alloc bytes1[] {0x01, 0x02, 0x03}
  615. assert_eq!(
  616. stringfy_expr!(
  617. &new_printer(&new_vartable()),
  618. &Expression::AllocDynamicBytes {
  619. loc: Loc::Codegen,
  620. ty: new_lir_type(Type::Bytes(1)),
  621. size: Box::new(num_literal!(3)),
  622. initializer: Some(vec![b'\x01', b'\x02', b'\x03']),
  623. }
  624. ),
  625. "alloc bytes1[uint8(3)] {01, 02, 03}"
  626. );
  627. }
  628. // GetRef
  629. #[test]
  630. fn test_stringfy_get_ref_expr() {
  631. let mut v = new_vartable();
  632. set_tmp(&mut v, 1, Type::Uint(8));
  633. let printer = new_printer(&v);
  634. // example: &ptr<uint8>(%temp.ssa_ir.1)
  635. assert_eq!(
  636. stringfy_expr!(
  637. &printer,
  638. &Expression::GetRef {
  639. loc: Loc::Codegen,
  640. operand: Box::new(identifier(1)),
  641. }
  642. ),
  643. "&uint8(%temp.ssa_ir.1)"
  644. );
  645. }
  646. // Load
  647. #[test]
  648. fn test_stringfy_load_expr() {
  649. let mut v = new_vartable();
  650. set_tmp(&mut v, 1, Type::Ptr(Box::new(Type::Bytes(1))));
  651. let printer = new_printer(&v);
  652. // example: *%1
  653. assert_eq!(
  654. stringfy_expr!(
  655. &printer,
  656. &Expression::Load {
  657. loc: Loc::Codegen,
  658. operand: Box::new(identifier(1)),
  659. }
  660. ),
  661. "*ptr<bytes1>(%temp.ssa_ir.1)"
  662. );
  663. }
  664. // StructMember
  665. #[test]
  666. fn test_stringfy_struct_member_expr() {
  667. let mut v = new_vartable();
  668. set_tmp(
  669. &mut v,
  670. 1,
  671. Type::Ptr(Box::new(Type::Struct(StructType::UserDefined(0)))),
  672. );
  673. let printer = new_printer(&v);
  674. // example: uint8 %1->1
  675. assert_eq!(
  676. stringfy_expr!(
  677. &printer,
  678. &Expression::StructMember {
  679. loc: Loc::Codegen,
  680. member: 3,
  681. operand: Box::new(identifier(1)),
  682. }
  683. ),
  684. "access ptr<struct.0>(%temp.ssa_ir.1) member 3"
  685. );
  686. }
  687. // Subscript
  688. #[test]
  689. fn test_stringfy_subscript_expr() {
  690. let mut v = new_vartable();
  691. set_tmp(
  692. &mut v,
  693. 1,
  694. Type::Ptr(Box::new(Type::Array(
  695. Box::new(Type::Uint(8)),
  696. vec![ArrayLength::Fixed(BigInt::from(2))],
  697. ))),
  698. );
  699. set_tmp(
  700. &mut v,
  701. 2,
  702. Type::Ptr(Box::new(Type::Array(
  703. Box::new(Type::Uint(8)),
  704. vec![ArrayLength::Dynamic],
  705. ))),
  706. );
  707. set_tmp(
  708. &mut v,
  709. 3,
  710. Type::Ptr(Box::new(Type::Array(
  711. Box::new(Type::Uint(8)),
  712. vec![ArrayLength::AnyFixed],
  713. ))),
  714. );
  715. let printer = new_printer(&v);
  716. // example: ptr<uint8[2]> %1[uint8(0)]
  717. assert_eq!(
  718. stringfy_expr!(
  719. &printer,
  720. &Expression::Subscript {
  721. loc: Loc::Codegen,
  722. arr: Box::new(identifier(1)),
  723. index: Box::new(num_literal!(0)),
  724. }
  725. ),
  726. "ptr<uint8[2]>(%temp.ssa_ir.1)[uint8(0)]"
  727. );
  728. // example: ptr<uint8[]> %1[uint8(0)]
  729. assert_eq!(
  730. stringfy_expr!(
  731. &printer,
  732. &Expression::Subscript {
  733. loc: Loc::Codegen,
  734. arr: Box::new(identifier(2)),
  735. index: Box::new(num_literal!(0)),
  736. }
  737. ),
  738. "ptr<uint8[]>(%temp.ssa_ir.2)[uint8(0)]"
  739. );
  740. // example: ptr<uint8[?]> %1[uint8(0)]
  741. assert_eq!(
  742. stringfy_expr!(
  743. &printer,
  744. &Expression::Subscript {
  745. loc: Loc::Codegen,
  746. arr: Box::new(identifier(3)),
  747. index: Box::new(num_literal!(0)),
  748. }
  749. ),
  750. "ptr<uint8[?]>(%temp.ssa_ir.3)[uint8(0)]"
  751. );
  752. }
  753. // AdvancePointer
  754. #[test]
  755. fn test_stringfy_advance_pointer_expr() {
  756. let mut v = new_vartable();
  757. set_tmp(
  758. &mut v,
  759. 1,
  760. Type::Ptr(Box::new(Type::Struct(StructType::UserDefined(0)))),
  761. );
  762. set_tmp(&mut v, 2, Type::Uint(8));
  763. let printer = new_printer(&v);
  764. // example: ptr_add(%1, %2)
  765. assert_eq!(
  766. stringfy_expr!(
  767. &printer,
  768. &Expression::AdvancePointer {
  769. loc: /*missing from cfg*/ Loc::Codegen,
  770. pointer: Box::new(identifier(1)),
  771. bytes_offset: Box::new(identifier(2)),
  772. }
  773. ),
  774. "ptr_add(ptr<struct.0>(%temp.ssa_ir.1), uint8(%temp.ssa_ir.2))"
  775. );
  776. // example: ptr_add(%1, uint8(1))
  777. assert_eq!(
  778. stringfy_expr!(
  779. &printer,
  780. &Expression::AdvancePointer {
  781. loc: /*missing from cfg*/ Loc::Codegen,
  782. pointer: Box::new(identifier(1)),
  783. bytes_offset: Box::new(num_literal!(1)),
  784. }
  785. ),
  786. "ptr_add(ptr<struct.0>(%temp.ssa_ir.1), uint8(1))"
  787. );
  788. }
  789. // FunctionArg
  790. #[test]
  791. fn test_stringfy_function_arg_expr() {
  792. // example: the 2nd arg of type uint8
  793. // (uint8 arg#2)
  794. assert_eq!(
  795. stringfy_expr!(
  796. &new_printer(&new_vartable()),
  797. &Expression::FunctionArg {
  798. loc: Loc::Codegen,
  799. ty: new_lir_type(Type::Uint(8)),
  800. arg_no: 2,
  801. }
  802. ),
  803. "uint8(arg#2)"
  804. );
  805. }
  806. // FormatString
  807. #[test]
  808. fn test_stringfy_format_string_expr() {
  809. let mut v = new_vartable();
  810. set_tmp(&mut v, 1, Type::Bytes(4));
  811. set_tmp(&mut v, 2, Type::Int(16));
  812. set_tmp(&mut v, 3, Type::Uint(8));
  813. set_tmp(&mut v, 4, Type::Uint(32));
  814. let printer = new_printer(&v);
  815. // case1: spec is empty:
  816. // fmt_str(%1)
  817. assert_eq!(
  818. stringfy_expr!(
  819. &printer,
  820. &Expression::FormatString {
  821. loc: Loc::Codegen,
  822. args: vec![(FormatArg::StringLiteral, identifier(1))]
  823. }
  824. ),
  825. "fmt_str(bytes4(%temp.ssa_ir.1))"
  826. );
  827. assert_eq!(
  828. stringfy_expr!(
  829. &printer,
  830. &Expression::FormatString {
  831. loc: Loc::Codegen,
  832. args: vec![(FormatArg::Default, identifier(2))]
  833. }
  834. ),
  835. "fmt_str(int16(%temp.ssa_ir.2))"
  836. );
  837. // case2: spec is binary:
  838. // fmt_str(:b %1)
  839. assert_eq!(
  840. stringfy_expr!(
  841. &printer,
  842. &Expression::FormatString {
  843. loc: Loc::Codegen,
  844. args: vec![(FormatArg::Binary, identifier(2))]
  845. }
  846. ),
  847. "fmt_str(:b int16(%temp.ssa_ir.2))"
  848. );
  849. // case3: spec is hex:
  850. // fmt_str(:x int16(%temp.ssa_ir.1))
  851. assert_eq!(
  852. stringfy_expr!(
  853. &printer,
  854. &Expression::FormatString {
  855. loc: Loc::Codegen,
  856. args: vec![(FormatArg::Hex, identifier(2))]
  857. }
  858. ),
  859. "fmt_str(:x int16(%temp.ssa_ir.2))"
  860. );
  861. // mixed case:
  862. // fmt_str(%1, %2, :b %2, :x %3)
  863. assert_eq!(
  864. stringfy_expr!(
  865. &printer,
  866. &Expression::FormatString {
  867. loc: Loc::Codegen,
  868. args: vec![
  869. (FormatArg::StringLiteral, identifier(1)),
  870. (FormatArg::Default, identifier(2)),
  871. (FormatArg::Binary, identifier(3)),
  872. (FormatArg::Hex, identifier(4))
  873. ]
  874. }
  875. ),
  876. "fmt_str(bytes4(%temp.ssa_ir.1), int16(%temp.ssa_ir.2), :b uint8(%temp.ssa_ir.3), :x uint32(%temp.ssa_ir.4))"
  877. );
  878. }
  879. // InternalFunctionCfg
  880. #[test]
  881. fn test_stringfy_internal_function_cfg_expr() {
  882. assert_eq!(
  883. stringfy_expr!(
  884. &new_printer(&new_vartable()),
  885. &Expression::InternalFunctionCfg { loc: /*missing from cfg*/ Loc::Codegen, cfg_no: 123 }
  886. ),
  887. "function#123"
  888. );
  889. }
  890. // Keccak256
  891. #[test]
  892. fn test_stringfy_keccak256_expr() {
  893. let mut v = new_vartable();
  894. set_tmp(&mut v, 1, Type::Bytes(4));
  895. set_tmp(&mut v, 2, Type::Bytes(4));
  896. let printer = new_printer(&v);
  897. // example: keccak256(%1, %2)
  898. assert_eq!(
  899. stringfy_expr!(
  900. &printer,
  901. &Expression::Keccak256 {
  902. loc: Loc::Codegen,
  903. args: vec![identifier(1), identifier(2)],
  904. }
  905. ),
  906. "keccak256(bytes4(%temp.ssa_ir.1), bytes4(%temp.ssa_ir.2))"
  907. );
  908. }
  909. // StringCompare
  910. #[test]
  911. fn test_stringfy_string_compare_expr() {
  912. let mut v = new_vartable();
  913. set_tmp(&mut v, 1, Type::Bytes(4));
  914. set_tmp(&mut v, 2, Type::Bytes(4));
  915. set_tmp(&mut v, 3, Type::Bytes(3));
  916. let printer = new_printer(&v);
  917. // case1: strcmp(%1, %2)
  918. assert_eq!(
  919. stringfy_expr!(
  920. &printer,
  921. &Expression::StringCompare {
  922. loc: Loc::Codegen,
  923. left: StringLocation::RunTime(Box::new(identifier(1))),
  924. right: StringLocation::RunTime(Box::new(identifier(2))),
  925. }
  926. ),
  927. "strcmp(bytes4(%temp.ssa_ir.1), bytes4(%temp.ssa_ir.2))"
  928. );
  929. // case2: strcmp("[97, 98, 99]", %1)
  930. assert_eq!(
  931. stringfy_expr!(
  932. &printer,
  933. &Expression::StringCompare {
  934. loc: Loc::Codegen,
  935. left: StringLocation::CompileTime(vec![b'a', b'b', b'c']),
  936. right: StringLocation::RunTime(Box::new(identifier(3))),
  937. }
  938. ),
  939. "strcmp(\"[97, 98, 99]\", bytes3(%temp.ssa_ir.3))"
  940. );
  941. // case3: strcmp(%1, "[97, 98, 99]")
  942. assert_eq!(
  943. stringfy_expr!(
  944. &printer,
  945. &Expression::StringCompare {
  946. loc: Loc::Codegen,
  947. left: StringLocation::RunTime(Box::new(identifier(3))),
  948. right: StringLocation::CompileTime(vec![b'a', b'b', b'c']),
  949. }
  950. ),
  951. "strcmp(bytes3(%temp.ssa_ir.3), \"[97, 98, 99]\")"
  952. );
  953. }
  954. // StringConcat
  955. #[test]
  956. fn test_stringfy_string_concat() {
  957. let mut v = new_vartable();
  958. set_tmp(&mut v, 1, Type::Bytes(4));
  959. set_tmp(&mut v, 2, Type::Bytes(2));
  960. let printer = new_printer(&v);
  961. // case1: strcat(%1, %2)
  962. assert_eq!(
  963. stringfy_expr!(
  964. &printer,
  965. &Expression::StringConcat {
  966. loc: Loc::Codegen,
  967. left: StringLocation::RunTime(Box::new(identifier(1))),
  968. right: StringLocation::RunTime(Box::new(identifier(2))),
  969. }
  970. ),
  971. "strcat(bytes4(%temp.ssa_ir.1), bytes2(%temp.ssa_ir.2))"
  972. );
  973. // case2: strcat("[97, 98, 99]", %1)
  974. assert_eq!(
  975. stringfy_expr!(
  976. &printer,
  977. &Expression::StringConcat {
  978. loc: Loc::Codegen,
  979. left: StringLocation::CompileTime(vec![b'a', b'b', b'c']),
  980. right: StringLocation::RunTime(Box::new(identifier(1))),
  981. }
  982. ),
  983. "strcat(\"[97, 98, 99]\", bytes4(%temp.ssa_ir.1))"
  984. );
  985. // case3: strcat(%1, "[97, 98, 99]")
  986. assert_eq!(
  987. stringfy_expr!(
  988. &printer,
  989. &Expression::StringConcat {
  990. loc: Loc::Codegen,
  991. left: StringLocation::RunTime(Box::new(identifier(1))),
  992. right: StringLocation::CompileTime(vec![b'a', b'b', b'c']),
  993. }
  994. ),
  995. "strcat(bytes4(%temp.ssa_ir.1), \"[97, 98, 99]\")"
  996. );
  997. }
  998. // StorageArrayLength
  999. #[test]
  1000. fn test_stringfy_storage_array_length() {
  1001. let mut v = new_vartable();
  1002. set_tmp(
  1003. &mut v,
  1004. 1,
  1005. Type::StoragePtr(
  1006. false,
  1007. Box::new(Type::Array(
  1008. Box::new(Type::Uint(8)),
  1009. vec![ArrayLength::Dynamic],
  1010. )),
  1011. ),
  1012. );
  1013. let printer = new_printer(&v);
  1014. // example: storage_arr_len(uint8[] %1)
  1015. assert_eq!(
  1016. stringfy_expr!(
  1017. &printer,
  1018. &Expression::StorageArrayLength {
  1019. loc: Loc::Codegen,
  1020. array: Box::new(identifier(1)),
  1021. }
  1022. ),
  1023. "storage_arr_len(storage_ptr<uint8[]>(%temp.ssa_ir.1))"
  1024. );
  1025. }
  1026. // ReturnData
  1027. #[test]
  1028. fn test_stringfy_return_data() {
  1029. // example: ret_data
  1030. assert_eq!(
  1031. stringfy_expr!(
  1032. &new_printer(&new_vartable()),
  1033. &Expression::ReturnData { loc: Loc::Codegen }
  1034. ),
  1035. "(extern_call_ret_data)"
  1036. );
  1037. }
  1038. #[test]
  1039. fn test_stringfy_builtin() {
  1040. let mut v = new_vartable();
  1041. set_tmp(&mut v, 1, Type::Int(16));
  1042. set_tmp(&mut v, 2, Type::Int(16));
  1043. let printer = new_printer(&v);
  1044. // example: builtin "addmod"(%1, %2, 0x100)
  1045. assert_eq!(
  1046. stringfy_expr!(
  1047. &printer,
  1048. &Expression::Builtin {
  1049. loc: Loc::Codegen,
  1050. kind: Builtin::AddMod,
  1051. args: vec![identifier(1), identifier(2), num_literal!(0x100, 16)],
  1052. }
  1053. ),
  1054. "builtin: AddMod(int16(%temp.ssa_ir.1), int16(%temp.ssa_ir.2), uint16(256))"
  1055. );
  1056. }