constant_folding.rs 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184
  1. // SPDX-License-Identifier: Apache-2.0
  2. use super::cfg::{ControlFlowGraph, Instr};
  3. use super::reaching_definitions;
  4. use crate::codegen::{Builtin, Expression};
  5. use crate::sema::ast::RetrieveType;
  6. use crate::sema::ast::{Diagnostic, Namespace, StringLocation, Type};
  7. use num_bigint::{BigInt, Sign};
  8. use num_traits::{ToPrimitive, Zero};
  9. use ripemd::Ripemd160;
  10. use sha2::{Digest, Sha256};
  11. use solang_parser::pt::Loc;
  12. use std::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Rem, Shl, Shr, Sub};
  13. use tiny_keccak::{Hasher, Keccak};
  14. /// Constant folding pass on the given cfg. During constant folding, we may find issues
  15. /// like divide by zero, so this function returns a list of diagnostics which should
  16. /// be added to the namespace.
  17. pub fn constant_folding(cfg: &mut ControlFlowGraph, ns: &mut Namespace) {
  18. // for each block, instruction
  19. for block_no in 0..cfg.blocks.len() {
  20. let mut vars = cfg.blocks[block_no].defs.clone();
  21. for instr_no in 0..cfg.blocks[block_no].instr.len() {
  22. match &cfg.blocks[block_no].instr[instr_no] {
  23. Instr::Set { loc, res, expr, .. } => {
  24. let (expr, expr_constant) = expression(expr, Some(&vars), cfg, ns);
  25. if expr_constant {
  26. ns.var_constants.insert(*loc, expr.clone());
  27. }
  28. cfg.blocks[block_no].instr[instr_no] = Instr::Set {
  29. loc: *loc,
  30. res: *res,
  31. expr,
  32. };
  33. }
  34. Instr::Call {
  35. res,
  36. call,
  37. args,
  38. return_tys,
  39. } => {
  40. let args = args
  41. .iter()
  42. .map(|e| expression(e, Some(&vars), cfg, ns).0)
  43. .collect();
  44. cfg.blocks[block_no].instr[instr_no] = Instr::Call {
  45. res: res.clone(),
  46. call: call.clone(),
  47. args,
  48. return_tys: return_tys.clone(),
  49. };
  50. }
  51. Instr::Return { value } => {
  52. let value = value
  53. .iter()
  54. .map(|e| expression(e, Some(&vars), cfg, ns).0)
  55. .collect();
  56. cfg.blocks[block_no].instr[instr_no] = Instr::Return { value };
  57. }
  58. Instr::BranchCond {
  59. cond,
  60. true_block,
  61. false_block,
  62. } => {
  63. let (cond, _) = expression(cond, Some(&vars), cfg, ns);
  64. if let Expression::BoolLiteral(_, cond) = cond {
  65. cfg.blocks[block_no].instr[instr_no] = Instr::Branch {
  66. block: if cond { *true_block } else { *false_block },
  67. };
  68. } else {
  69. cfg.blocks[block_no].instr[instr_no] = Instr::BranchCond {
  70. cond,
  71. true_block: *true_block,
  72. false_block: *false_block,
  73. };
  74. }
  75. }
  76. Instr::Store { dest, data } => {
  77. let (dest, _) = expression(dest, Some(&vars), cfg, ns);
  78. let (data, _) = expression(data, Some(&vars), cfg, ns);
  79. cfg.blocks[block_no].instr[instr_no] = Instr::Store { dest, data };
  80. }
  81. Instr::AssertFailure { expr: Some(expr) } => {
  82. let (expr, _) = expression(expr, Some(&vars), cfg, ns);
  83. cfg.blocks[block_no].instr[instr_no] =
  84. Instr::AssertFailure { expr: Some(expr) };
  85. }
  86. Instr::Print { expr } => {
  87. let (expr, _) = expression(expr, Some(&vars), cfg, ns);
  88. cfg.blocks[block_no].instr[instr_no] = Instr::Print { expr };
  89. }
  90. Instr::ClearStorage { ty, storage } => {
  91. let (storage, _) = expression(storage, Some(&vars), cfg, ns);
  92. cfg.blocks[block_no].instr[instr_no] = Instr::ClearStorage {
  93. ty: ty.clone(),
  94. storage,
  95. };
  96. }
  97. Instr::SetStorage { ty, storage, value } => {
  98. let (storage, _) = expression(storage, Some(&vars), cfg, ns);
  99. let (value, _) = expression(value, Some(&vars), cfg, ns);
  100. cfg.blocks[block_no].instr[instr_no] = Instr::SetStorage {
  101. ty: ty.clone(),
  102. storage,
  103. value,
  104. };
  105. }
  106. Instr::LoadStorage { ty, storage, res } => {
  107. let (storage, _) = expression(storage, Some(&vars), cfg, ns);
  108. cfg.blocks[block_no].instr[instr_no] = Instr::LoadStorage {
  109. ty: ty.clone(),
  110. storage,
  111. res: *res,
  112. };
  113. }
  114. Instr::SetStorageBytes {
  115. storage,
  116. value,
  117. offset,
  118. } => {
  119. let (storage, _) = expression(storage, Some(&vars), cfg, ns);
  120. let (value, _) = expression(value, Some(&vars), cfg, ns);
  121. let (offset, _) = expression(offset, Some(&vars), cfg, ns);
  122. cfg.blocks[block_no].instr[instr_no] = Instr::SetStorageBytes {
  123. storage,
  124. value,
  125. offset,
  126. };
  127. }
  128. Instr::PushStorage {
  129. res,
  130. ty,
  131. storage,
  132. value,
  133. } => {
  134. let (storage, _) = expression(storage, Some(&vars), cfg, ns);
  135. let value = value
  136. .as_ref()
  137. .map(|expr| expression(expr, Some(&vars), cfg, ns).0);
  138. cfg.blocks[block_no].instr[instr_no] = Instr::PushStorage {
  139. res: *res,
  140. ty: ty.clone(),
  141. storage,
  142. value,
  143. };
  144. }
  145. Instr::PopStorage { res, ty, storage } => {
  146. let (storage, _) = expression(storage, Some(&vars), cfg, ns);
  147. cfg.blocks[block_no].instr[instr_no] = Instr::PopStorage {
  148. res: *res,
  149. ty: ty.clone(),
  150. storage,
  151. };
  152. }
  153. Instr::PushMemory {
  154. res,
  155. ty,
  156. array,
  157. value,
  158. } => {
  159. let (value, _) = expression(value, Some(&vars), cfg, ns);
  160. cfg.blocks[block_no].instr[instr_no] = Instr::PushMemory {
  161. res: *res,
  162. ty: ty.clone(),
  163. array: *array,
  164. value: Box::new(value),
  165. };
  166. }
  167. Instr::Constructor {
  168. success,
  169. res,
  170. contract_no,
  171. constructor_no,
  172. args,
  173. value,
  174. gas,
  175. salt,
  176. space,
  177. } => {
  178. let args = args
  179. .iter()
  180. .map(|e| expression(e, Some(&vars), cfg, ns).0)
  181. .collect();
  182. let value = value
  183. .as_ref()
  184. .map(|expr| expression(expr, Some(&vars), cfg, ns).0);
  185. let gas = expression(gas, Some(&vars), cfg, ns).0;
  186. let salt = salt
  187. .as_ref()
  188. .map(|expr| expression(expr, Some(&vars), cfg, ns).0);
  189. let space = space
  190. .as_ref()
  191. .map(|expr| expression(expr, Some(&vars), cfg, ns).0);
  192. cfg.blocks[block_no].instr[instr_no] = Instr::Constructor {
  193. success: *success,
  194. res: *res,
  195. contract_no: *contract_no,
  196. constructor_no: *constructor_no,
  197. args,
  198. value,
  199. gas,
  200. salt,
  201. space,
  202. };
  203. }
  204. Instr::ExternalCall {
  205. success,
  206. address,
  207. payload,
  208. value,
  209. gas,
  210. accounts,
  211. seeds,
  212. callty,
  213. } => {
  214. let value = expression(value, Some(&vars), cfg, ns).0;
  215. let gas = expression(gas, Some(&vars), cfg, ns).0;
  216. let payload = expression(payload, Some(&vars), cfg, ns).0;
  217. let address = address
  218. .as_ref()
  219. .map(|expr| expression(expr, Some(&vars), cfg, ns).0);
  220. let accounts = accounts
  221. .as_ref()
  222. .map(|expr| expression(expr, Some(&vars), cfg, ns).0);
  223. let seeds = seeds
  224. .as_ref()
  225. .map(|expr| expression(expr, Some(&vars), cfg, ns).0);
  226. cfg.blocks[block_no].instr[instr_no] = Instr::ExternalCall {
  227. success: *success,
  228. address,
  229. accounts,
  230. seeds,
  231. payload,
  232. value,
  233. gas,
  234. callty: callty.clone(),
  235. };
  236. }
  237. Instr::AbiDecode {
  238. res,
  239. selector,
  240. exception_block,
  241. tys,
  242. data,
  243. } => {
  244. let (data, _) = expression(data, Some(&vars), cfg, ns);
  245. cfg.blocks[block_no].instr[instr_no] = Instr::AbiDecode {
  246. res: res.clone(),
  247. selector: *selector,
  248. exception_block: *exception_block,
  249. tys: tys.clone(),
  250. data,
  251. }
  252. }
  253. Instr::SelfDestruct { recipient } => {
  254. let (recipient, _) = expression(recipient, Some(&vars), cfg, ns);
  255. cfg.blocks[block_no].instr[instr_no] = Instr::SelfDestruct { recipient };
  256. }
  257. Instr::EmitEvent {
  258. event_no,
  259. data,
  260. data_tys,
  261. topics,
  262. topic_tys,
  263. } => {
  264. let data = data
  265. .iter()
  266. .map(|e| expression(e, Some(&vars), cfg, ns).0)
  267. .collect();
  268. let topics = topics
  269. .iter()
  270. .map(|e| expression(e, Some(&vars), cfg, ns).0)
  271. .collect();
  272. cfg.blocks[block_no].instr[instr_no] = Instr::EmitEvent {
  273. event_no: *event_no,
  274. data,
  275. data_tys: data_tys.clone(),
  276. topics,
  277. topic_tys: topic_tys.clone(),
  278. }
  279. }
  280. Instr::MemCopy {
  281. source,
  282. destination,
  283. bytes,
  284. } => {
  285. let bytes = expression(bytes, Some(&vars), cfg, ns);
  286. let source = expression(source, Some(&vars), cfg, ns);
  287. let destination = expression(destination, Some(&vars), cfg, ns);
  288. cfg.blocks[block_no].instr[instr_no] = Instr::MemCopy {
  289. source: source.0,
  290. destination: destination.0,
  291. bytes: bytes.0,
  292. };
  293. }
  294. _ => (),
  295. }
  296. reaching_definitions::apply_transfers(
  297. &cfg.blocks[block_no].transfers[instr_no],
  298. &mut vars,
  299. );
  300. }
  301. }
  302. }
  303. /// Recursively walk the expression and fold any constant expressions or variables. This function returns the
  304. /// constant folded expression, and a boolean which is true if the value is "pure", the value does not depend
  305. /// on context. This is used for constant folding, so that e.g. an external function call is not constant
  306. /// folded (and moved/copied as a result).
  307. fn expression(
  308. expr: &Expression,
  309. vars: Option<&reaching_definitions::VarDefs>,
  310. cfg: &ControlFlowGraph,
  311. ns: &mut Namespace,
  312. ) -> (Expression, bool) {
  313. match expr {
  314. Expression::Add(loc, ty, unchecked, left, right) => {
  315. let left = expression(left, vars, cfg, ns);
  316. let right = expression(right, vars, cfg, ns);
  317. if let (Expression::NumberLiteral(_, _, left), Expression::NumberLiteral(_, _, right)) =
  318. (&left.0, &right.0)
  319. {
  320. bigint_to_expression(loc, ty, left.add(right))
  321. } else {
  322. (
  323. Expression::Add(
  324. *loc,
  325. ty.clone(),
  326. *unchecked,
  327. Box::new(left.0),
  328. Box::new(right.0),
  329. ),
  330. left.1 && right.1,
  331. )
  332. }
  333. }
  334. Expression::Subtract(loc, ty, unchecked, left, right) => {
  335. let left = expression(left, vars, cfg, ns);
  336. let right = expression(right, vars, cfg, ns);
  337. if let (Expression::NumberLiteral(_, _, left), Expression::NumberLiteral(_, _, right)) =
  338. (&left.0, &right.0)
  339. {
  340. bigint_to_expression(loc, ty, left.sub(right))
  341. } else {
  342. (
  343. Expression::Subtract(
  344. *loc,
  345. ty.clone(),
  346. *unchecked,
  347. Box::new(left.0),
  348. Box::new(right.0),
  349. ),
  350. left.1 && right.1,
  351. )
  352. }
  353. }
  354. Expression::AdvancePointer {
  355. pointer,
  356. bytes_offset: offset,
  357. } => {
  358. // Only the offset can be simplified
  359. let offset = expression(offset, vars, cfg, ns);
  360. match &offset.0 {
  361. // There is no reason to advance the pointer by a zero offset
  362. Expression::NumberLiteral(_, _, num) if num.is_zero() => (*pointer.clone(), false),
  363. _ => (
  364. Expression::AdvancePointer {
  365. pointer: pointer.clone(),
  366. bytes_offset: Box::new(offset.0),
  367. },
  368. offset.1,
  369. ),
  370. }
  371. }
  372. Expression::Multiply(loc, ty, unchecked, left, right) => {
  373. let left = expression(left, vars, cfg, ns);
  374. let right = expression(right, vars, cfg, ns);
  375. if let (Expression::NumberLiteral(_, _, left), Expression::NumberLiteral(_, _, right)) =
  376. (&left.0, &right.0)
  377. {
  378. bigint_to_expression(loc, ty, left.mul(right))
  379. } else {
  380. (
  381. Expression::Multiply(
  382. *loc,
  383. ty.clone(),
  384. *unchecked,
  385. Box::new(left.0),
  386. Box::new(right.0),
  387. ),
  388. left.1 && right.1,
  389. )
  390. }
  391. }
  392. Expression::BitwiseAnd(loc, ty, left, right) => {
  393. let left = expression(left, vars, cfg, ns);
  394. let right = expression(right, vars, cfg, ns);
  395. if let (Expression::NumberLiteral(_, _, left), Expression::NumberLiteral(_, _, right)) =
  396. (&left.0, &right.0)
  397. {
  398. bigint_to_expression(loc, ty, left.bitand(right))
  399. } else {
  400. (
  401. Expression::BitwiseAnd(*loc, ty.clone(), Box::new(left.0), Box::new(right.0)),
  402. left.1 && right.1,
  403. )
  404. }
  405. }
  406. Expression::BitwiseOr(loc, ty, left, right) => {
  407. let left = expression(left, vars, cfg, ns);
  408. let right = expression(right, vars, cfg, ns);
  409. if let (Expression::NumberLiteral(_, _, left), Expression::NumberLiteral(_, _, right)) =
  410. (&left.0, &right.0)
  411. {
  412. bigint_to_expression(loc, ty, left.bitor(right))
  413. } else {
  414. (
  415. Expression::BitwiseOr(*loc, ty.clone(), Box::new(left.0), Box::new(right.0)),
  416. left.1 && right.1,
  417. )
  418. }
  419. }
  420. Expression::BitwiseXor(loc, ty, left, right) => {
  421. let left = expression(left, vars, cfg, ns);
  422. let right = expression(right, vars, cfg, ns);
  423. if let (Expression::NumberLiteral(_, _, left), Expression::NumberLiteral(_, _, right)) =
  424. (&left.0, &right.0)
  425. {
  426. bigint_to_expression(loc, ty, left.bitxor(right))
  427. } else {
  428. (
  429. Expression::BitwiseXor(*loc, ty.clone(), Box::new(left.0), Box::new(right.0)),
  430. left.1 && right.1,
  431. )
  432. }
  433. }
  434. Expression::ShiftLeft(loc, ty, left_expr, right_expr) => {
  435. let left = expression(left_expr, vars, cfg, ns);
  436. let right = expression(right_expr, vars, cfg, ns);
  437. if let (Expression::NumberLiteral(_, _, left), Expression::NumberLiteral(_, _, right)) =
  438. (&left.0, &right.0)
  439. {
  440. if right.sign() == Sign::Minus || right >= &BigInt::from(left_expr.ty().bits(ns)) {
  441. ns.diagnostics.push(Diagnostic::error(
  442. *loc,
  443. format!("left shift by {} is not possible", right),
  444. ));
  445. } else {
  446. let right: u64 = right.to_u64().unwrap();
  447. return bigint_to_expression(loc, ty, left.shl(&right));
  448. }
  449. }
  450. (
  451. Expression::ShiftLeft(*loc, ty.clone(), Box::new(left.0), Box::new(right.0)),
  452. left.1 && right.1,
  453. )
  454. }
  455. Expression::ShiftRight(loc, ty, left_expr, right_expr, signed) => {
  456. let left = expression(left_expr, vars, cfg, ns);
  457. let right = expression(right_expr, vars, cfg, ns);
  458. if let (Expression::NumberLiteral(_, _, left), Expression::NumberLiteral(_, _, right)) =
  459. (&left.0, &right.0)
  460. {
  461. if right.sign() == Sign::Minus || right >= &BigInt::from(left_expr.ty().bits(ns)) {
  462. ns.diagnostics.push(Diagnostic::error(
  463. *loc,
  464. format!("right shift by {} is not possible", right),
  465. ));
  466. } else {
  467. let right: u64 = right.to_u64().unwrap();
  468. return bigint_to_expression(loc, ty, left.shr(&right));
  469. }
  470. }
  471. (
  472. Expression::ShiftRight(
  473. *loc,
  474. ty.clone(),
  475. Box::new(left.0),
  476. Box::new(right.0),
  477. *signed,
  478. ),
  479. left.1 && right.1,
  480. )
  481. }
  482. Expression::Power(loc, ty, unchecked, left, right) => {
  483. let left = expression(left, vars, cfg, ns);
  484. let right = expression(right, vars, cfg, ns);
  485. if let (Expression::NumberLiteral(_, _, left), Expression::NumberLiteral(_, _, right)) =
  486. (&left.0, &right.0)
  487. {
  488. if right.sign() == Sign::Minus || right >= &BigInt::from(u32::MAX) {
  489. ns.diagnostics.push(Diagnostic::error(
  490. *loc,
  491. format!("power {} not possible", right),
  492. ));
  493. } else {
  494. let right: u32 = right.to_u32().unwrap();
  495. return bigint_to_expression(loc, ty, left.pow(right));
  496. }
  497. }
  498. (
  499. Expression::Power(
  500. *loc,
  501. ty.clone(),
  502. *unchecked,
  503. Box::new(left.0),
  504. Box::new(right.0),
  505. ),
  506. left.1 && right.1,
  507. )
  508. }
  509. Expression::UnsignedDivide(loc, ty, left, right)
  510. | Expression::SignedDivide(loc, ty, left, right) => {
  511. let left = expression(left, vars, cfg, ns);
  512. let right = expression(right, vars, cfg, ns);
  513. if let Expression::NumberLiteral(_, _, right) = &right.0 {
  514. if right.is_zero() {
  515. ns.diagnostics
  516. .push(Diagnostic::error(*loc, String::from("divide by zero")));
  517. } else if let Expression::NumberLiteral(_, _, left) = &left.0 {
  518. return bigint_to_expression(loc, ty, left.div(right));
  519. }
  520. }
  521. (
  522. if matches!(expr, Expression::SignedDivide(..)) {
  523. Expression::SignedDivide(*loc, ty.clone(), Box::new(left.0), Box::new(right.0))
  524. } else {
  525. Expression::UnsignedDivide(
  526. *loc,
  527. ty.clone(),
  528. Box::new(left.0),
  529. Box::new(right.0),
  530. )
  531. },
  532. left.1 && right.1,
  533. )
  534. }
  535. Expression::SignedModulo(loc, ty, left, right)
  536. | Expression::UnsignedModulo(loc, ty, left, right) => {
  537. let left = expression(left, vars, cfg, ns);
  538. let right = expression(right, vars, cfg, ns);
  539. if let Expression::NumberLiteral(_, _, right) = &right.0 {
  540. if right.is_zero() {
  541. ns.diagnostics
  542. .push(Diagnostic::error(*loc, String::from("divide by zero")));
  543. } else if let Expression::NumberLiteral(_, _, left) = &left.0 {
  544. return bigint_to_expression(loc, ty, left.rem(right));
  545. }
  546. }
  547. (
  548. if matches!(expr, Expression::SignedModulo(..)) {
  549. Expression::SignedModulo(*loc, ty.clone(), Box::new(left.0), Box::new(right.0))
  550. } else {
  551. Expression::UnsignedModulo(
  552. *loc,
  553. ty.clone(),
  554. Box::new(left.0),
  555. Box::new(right.0),
  556. )
  557. },
  558. left.1 && right.1,
  559. )
  560. }
  561. Expression::ZeroExt(loc, ty, expr) => {
  562. let expr = expression(expr, vars, cfg, ns);
  563. if let Expression::NumberLiteral(_, _, n) = expr.0 {
  564. (Expression::NumberLiteral(*loc, ty.clone(), n), true)
  565. } else {
  566. (
  567. Expression::ZeroExt(*loc, ty.clone(), Box::new(expr.0)),
  568. expr.1,
  569. )
  570. }
  571. }
  572. Expression::SignExt(loc, ty, expr) => {
  573. let expr = expression(expr, vars, cfg, ns);
  574. if let Expression::NumberLiteral(_, _, n) = expr.0 {
  575. (Expression::NumberLiteral(*loc, ty.clone(), n), true)
  576. } else {
  577. (
  578. Expression::SignExt(*loc, ty.clone(), Box::new(expr.0)),
  579. expr.1,
  580. )
  581. }
  582. }
  583. Expression::Trunc(loc, ty, expr) => {
  584. let expr = expression(expr, vars, cfg, ns);
  585. if let Expression::NumberLiteral(_, _, n) = expr.0 {
  586. bigint_to_expression(loc, ty, n)
  587. } else {
  588. (
  589. Expression::Trunc(*loc, ty.clone(), Box::new(expr.0)),
  590. expr.1,
  591. )
  592. }
  593. }
  594. Expression::Complement(loc, ty, expr) => {
  595. let expr = expression(expr, vars, cfg, ns);
  596. if let Expression::NumberLiteral(_, _, n) = expr.0 {
  597. bigint_to_expression(loc, ty, !n)
  598. } else {
  599. (
  600. Expression::Complement(*loc, ty.clone(), Box::new(expr.0)),
  601. expr.1,
  602. )
  603. }
  604. }
  605. Expression::UnaryMinus(loc, ty, expr) => {
  606. let expr = expression(expr, vars, cfg, ns);
  607. if let Expression::NumberLiteral(_, _, n) = expr.0 {
  608. bigint_to_expression(loc, ty, -n)
  609. } else {
  610. (
  611. Expression::UnaryMinus(*loc, ty.clone(), Box::new(expr.0)),
  612. expr.1,
  613. )
  614. }
  615. }
  616. Expression::Variable(loc, ty, var) => {
  617. if !matches!(ty, Type::Ref(_) | Type::StorageRef(..)) {
  618. if let Some(vars) = vars {
  619. if let Some(defs) = vars.get(var) {
  620. // There must be at least one definition, and all should evaluate to the same value
  621. let mut v = None;
  622. for def in defs.keys() {
  623. if let Some(expr) = get_definition(def, cfg) {
  624. let expr = expression(expr, None, cfg, ns);
  625. if expr.1 {
  626. if let Some(last) = &v {
  627. if !constants_equal(last, &expr.0) {
  628. v = None;
  629. break;
  630. }
  631. }
  632. v = Some(expr.0);
  633. } else {
  634. v = None;
  635. break;
  636. }
  637. } else {
  638. v = None;
  639. break;
  640. }
  641. }
  642. if let Some(expr) = v {
  643. if *loc != Loc::Codegen {
  644. ns.var_constants.insert(*loc, expr.clone());
  645. }
  646. return (expr, true);
  647. }
  648. }
  649. }
  650. }
  651. (expr.clone(), false)
  652. }
  653. Expression::Builtin(loc, tys, Builtin::Keccak256, args) => {
  654. let arg = expression(&args[0], vars, cfg, ns);
  655. if let Expression::AllocDynamicArray(_, _, _, Some(bs)) = arg.0 {
  656. let mut hasher = Keccak::v256();
  657. hasher.update(&bs);
  658. let mut hash = [0u8; 32];
  659. hasher.finalize(&mut hash);
  660. (
  661. Expression::BytesLiteral(*loc, tys[0].clone(), hash.to_vec()),
  662. true,
  663. )
  664. } else {
  665. (
  666. Expression::Builtin(*loc, tys.clone(), Builtin::Keccak256, vec![arg.0]),
  667. false,
  668. )
  669. }
  670. }
  671. Expression::Builtin(loc, tys, Builtin::Ripemd160, args) => {
  672. let arg = expression(&args[0], vars, cfg, ns);
  673. if let Expression::AllocDynamicArray(_, _, _, Some(bs)) = arg.0 {
  674. let mut hasher = Ripemd160::new();
  675. hasher.update(&bs);
  676. let result = hasher.finalize();
  677. (
  678. Expression::BytesLiteral(*loc, tys[0].clone(), result[..].to_vec()),
  679. true,
  680. )
  681. } else {
  682. (
  683. Expression::Builtin(*loc, tys.clone(), Builtin::Ripemd160, vec![arg.0]),
  684. false,
  685. )
  686. }
  687. }
  688. Expression::Builtin(loc, tys, Builtin::Blake2_256, args) => {
  689. let arg = expression(&args[0], vars, cfg, ns);
  690. if let Expression::AllocDynamicArray(_, _, _, Some(bs)) = arg.0 {
  691. let hash = blake2_rfc::blake2b::blake2b(32, &[], &bs);
  692. (
  693. Expression::BytesLiteral(*loc, tys[0].clone(), hash.as_bytes().to_vec()),
  694. true,
  695. )
  696. } else {
  697. (
  698. Expression::Builtin(*loc, tys.clone(), Builtin::Blake2_256, vec![arg.0]),
  699. false,
  700. )
  701. }
  702. }
  703. Expression::Builtin(loc, tys, Builtin::Blake2_128, args) => {
  704. let arg = expression(&args[0], vars, cfg, ns);
  705. if let Expression::AllocDynamicArray(_, _, _, Some(bs)) = arg.0 {
  706. let hash = blake2_rfc::blake2b::blake2b(16, &[], &bs);
  707. (
  708. Expression::BytesLiteral(*loc, tys[0].clone(), hash.as_bytes().to_vec()),
  709. true,
  710. )
  711. } else {
  712. (
  713. Expression::Builtin(*loc, tys.clone(), Builtin::Blake2_128, vec![arg.0]),
  714. false,
  715. )
  716. }
  717. }
  718. Expression::Builtin(loc, tys, Builtin::Sha256, args) => {
  719. let arg = expression(&args[0], vars, cfg, ns);
  720. if let Expression::AllocDynamicArray(_, _, _, Some(bs)) = arg.0 {
  721. let mut hasher = Sha256::new();
  722. // write input message
  723. hasher.update(&bs);
  724. // read hash digest and consume hasher
  725. let result = hasher.finalize();
  726. (
  727. Expression::BytesLiteral(*loc, tys[0].clone(), result[..].to_vec()),
  728. true,
  729. )
  730. } else {
  731. (
  732. Expression::Builtin(*loc, tys.clone(), Builtin::Sha256, vec![arg.0]),
  733. false,
  734. )
  735. }
  736. }
  737. Expression::Keccak256(loc, ty, args) => {
  738. let mut all_constant = true;
  739. let mut hasher = Keccak::v256();
  740. let args = args
  741. .iter()
  742. .map(|expr| {
  743. let (expr, _) = expression(expr, vars, cfg, ns);
  744. if all_constant {
  745. match &expr {
  746. Expression::AllocDynamicArray(_, _, _, Some(bs))
  747. | Expression::BytesLiteral(_, _, bs) => {
  748. hasher.update(bs);
  749. }
  750. Expression::NumberLiteral(_, ty, n) => {
  751. let (sign, mut bs) = n.to_bytes_le();
  752. match ty {
  753. Type::Uint(bits) => bs.resize(*bits as usize / 8, 0),
  754. Type::Int(bits) => {
  755. let v = if sign == Sign::Minus { 0xffu8 } else { 0 };
  756. bs.resize(*bits as usize / 8, v);
  757. }
  758. Type::Bytes(n) => {
  759. while (*n as usize) < bs.len() {
  760. bs.insert(0, 0);
  761. }
  762. }
  763. Type::Address(_) => {
  764. bs.resize(ns.address_length, 0);
  765. }
  766. _ => unreachable!(),
  767. }
  768. hasher.update(&bs);
  769. }
  770. _ => {
  771. all_constant = false;
  772. }
  773. }
  774. }
  775. expr
  776. })
  777. .collect();
  778. if all_constant {
  779. let mut hash = [0u8; 32];
  780. hasher.finalize(&mut hash);
  781. let mut hash = hash.to_vec();
  782. hash.reverse();
  783. (Expression::BytesLiteral(*loc, ty.clone(), hash), true)
  784. } else {
  785. (Expression::Keccak256(*loc, ty.clone(), args), false)
  786. }
  787. }
  788. // The rest is simply for recursing; no constant expansion should be done
  789. Expression::StructLiteral(loc, ty, args) => {
  790. let args = args
  791. .iter()
  792. .map(|expr| expression(expr, vars, cfg, ns).0)
  793. .collect();
  794. (Expression::StructLiteral(*loc, ty.clone(), args), false)
  795. }
  796. Expression::ArrayLiteral(loc, ty, lengths, args) => {
  797. let args = args
  798. .iter()
  799. .map(|expr| expression(expr, vars, cfg, ns).0)
  800. .collect();
  801. (
  802. Expression::ArrayLiteral(*loc, ty.clone(), lengths.clone(), args),
  803. false,
  804. )
  805. }
  806. Expression::ConstArrayLiteral(loc, ty, lengths, args) => {
  807. let args = args
  808. .iter()
  809. .map(|expr| expression(expr, vars, cfg, ns).0)
  810. .collect();
  811. (
  812. Expression::ConstArrayLiteral(*loc, ty.clone(), lengths.clone(), args),
  813. false,
  814. )
  815. }
  816. Expression::Load(loc, ty, expr) => {
  817. let (expr, _) = expression(expr, vars, cfg, ns);
  818. (Expression::Load(*loc, ty.clone(), Box::new(expr)), false)
  819. }
  820. Expression::Cast(loc, ty, expr) => {
  821. let (expr, _) = expression(expr, vars, cfg, ns);
  822. (Expression::Cast(*loc, ty.clone(), Box::new(expr)), false)
  823. }
  824. Expression::BytesCast(loc, from, to, expr) => {
  825. let (expr, _) = expression(expr, vars, cfg, ns);
  826. (
  827. Expression::BytesCast(*loc, from.clone(), to.clone(), Box::new(expr)),
  828. false,
  829. )
  830. }
  831. Expression::UnsignedMore(loc, left, right) => {
  832. let left = expression(left, vars, cfg, ns);
  833. let right = expression(right, vars, cfg, ns);
  834. (
  835. Expression::UnsignedMore(*loc, Box::new(left.0), Box::new(right.0)),
  836. false,
  837. )
  838. }
  839. Expression::SignedMore(loc, left, right) => {
  840. let left = expression(left, vars, cfg, ns);
  841. let right = expression(right, vars, cfg, ns);
  842. (
  843. Expression::SignedMore(*loc, Box::new(left.0), Box::new(right.0)),
  844. false,
  845. )
  846. }
  847. Expression::SignedLess(loc, left, right) => {
  848. let left = expression(left, vars, cfg, ns);
  849. let right = expression(right, vars, cfg, ns);
  850. (
  851. Expression::SignedLess(*loc, Box::new(left.0), Box::new(right.0)),
  852. false,
  853. )
  854. }
  855. Expression::UnsignedLess(loc, left, right) => {
  856. let left = expression(left, vars, cfg, ns);
  857. let right = expression(right, vars, cfg, ns);
  858. (
  859. Expression::UnsignedLess(*loc, Box::new(left.0), Box::new(right.0)),
  860. false,
  861. )
  862. }
  863. Expression::MoreEqual(loc, left, right) => {
  864. let left = expression(left, vars, cfg, ns);
  865. let right = expression(right, vars, cfg, ns);
  866. (
  867. Expression::MoreEqual(*loc, Box::new(left.0), Box::new(right.0)),
  868. false,
  869. )
  870. }
  871. Expression::LessEqual(loc, left, right) => {
  872. let left = expression(left, vars, cfg, ns);
  873. let right = expression(right, vars, cfg, ns);
  874. (
  875. Expression::LessEqual(*loc, Box::new(left.0), Box::new(right.0)),
  876. false,
  877. )
  878. }
  879. Expression::Equal(loc, left, right) => {
  880. let left = expression(left, vars, cfg, ns);
  881. let right = expression(right, vars, cfg, ns);
  882. (
  883. Expression::Equal(*loc, Box::new(left.0), Box::new(right.0)),
  884. false,
  885. )
  886. }
  887. Expression::NotEqual(loc, left, right) => {
  888. let left = expression(left, vars, cfg, ns);
  889. let right = expression(right, vars, cfg, ns);
  890. (
  891. Expression::NotEqual(*loc, Box::new(left.0), Box::new(right.0)),
  892. false,
  893. )
  894. }
  895. Expression::Not(loc, expr) => {
  896. let expr = expression(expr, vars, cfg, ns);
  897. (Expression::Not(*loc, Box::new(expr.0)), expr.1)
  898. }
  899. Expression::Subscript(loc, ty, array_ty, array, index) => {
  900. let array = expression(array, vars, cfg, ns);
  901. let index = expression(index, vars, cfg, ns);
  902. (
  903. Expression::Subscript(
  904. *loc,
  905. ty.clone(),
  906. array_ty.clone(),
  907. Box::new(array.0),
  908. Box::new(index.0),
  909. ),
  910. false,
  911. )
  912. }
  913. Expression::StructMember(loc, ty, strct, member) => {
  914. let strct = expression(strct, vars, cfg, ns);
  915. (
  916. Expression::StructMember(*loc, ty.clone(), Box::new(strct.0), *member),
  917. false,
  918. )
  919. }
  920. Expression::StorageArrayLength {
  921. loc,
  922. ty,
  923. array,
  924. elem_ty,
  925. } => {
  926. let array = expression(array, vars, cfg, ns);
  927. (
  928. Expression::StorageArrayLength {
  929. loc: *loc,
  930. ty: ty.clone(),
  931. array: Box::new(array.0),
  932. elem_ty: elem_ty.clone(),
  933. },
  934. false,
  935. )
  936. }
  937. Expression::StringCompare(loc, left, right) => {
  938. if let (StringLocation::CompileTime(left), StringLocation::CompileTime(right)) =
  939. (left, right)
  940. {
  941. (Expression::BoolLiteral(*loc, left == right), true)
  942. } else {
  943. let left = if let StringLocation::RunTime(left) = left {
  944. StringLocation::RunTime(Box::new(expression(left, vars, cfg, ns).0))
  945. } else {
  946. left.clone()
  947. };
  948. let right = if let StringLocation::RunTime(right) = right {
  949. StringLocation::RunTime(Box::new(expression(right, vars, cfg, ns).0))
  950. } else {
  951. right.clone()
  952. };
  953. (Expression::StringCompare(*loc, left, right), false)
  954. }
  955. }
  956. Expression::StringConcat(loc, ty, left, right) => {
  957. if let (StringLocation::CompileTime(left), StringLocation::CompileTime(right)) =
  958. (left, right)
  959. {
  960. let mut bs = Vec::with_capacity(left.len() + right.len());
  961. bs.extend(left);
  962. bs.extend(right);
  963. (Expression::BytesLiteral(*loc, ty.clone(), bs), true)
  964. } else {
  965. let left = if let StringLocation::RunTime(left) = left {
  966. StringLocation::RunTime(Box::new(expression(left, vars, cfg, ns).0))
  967. } else {
  968. left.clone()
  969. };
  970. let right = if let StringLocation::RunTime(right) = right {
  971. StringLocation::RunTime(Box::new(expression(right, vars, cfg, ns).0))
  972. } else {
  973. right.clone()
  974. };
  975. (
  976. Expression::StringConcat(*loc, ty.clone(), left, right),
  977. false,
  978. )
  979. }
  980. }
  981. Expression::Builtin(loc, tys, builtin, args) => {
  982. let args = args
  983. .iter()
  984. .map(|expr| expression(expr, vars, cfg, ns).0)
  985. .collect();
  986. (
  987. Expression::Builtin(*loc, tys.clone(), *builtin, args),
  988. false,
  989. )
  990. }
  991. Expression::AbiEncode {
  992. loc,
  993. tys,
  994. packed,
  995. args,
  996. } => {
  997. let packed = packed
  998. .iter()
  999. .map(|expr| expression(expr, vars, cfg, ns).0)
  1000. .collect();
  1001. let args = args
  1002. .iter()
  1003. .map(|expr| expression(expr, vars, cfg, ns).0)
  1004. .collect();
  1005. (
  1006. Expression::AbiEncode {
  1007. loc: *loc,
  1008. tys: tys.clone(),
  1009. packed,
  1010. args,
  1011. },
  1012. false,
  1013. )
  1014. }
  1015. Expression::NumberLiteral(..)
  1016. | Expression::RationalNumberLiteral(..)
  1017. | Expression::BoolLiteral(..)
  1018. | Expression::BytesLiteral(..)
  1019. | Expression::CodeLiteral(..)
  1020. | Expression::FunctionArg(..) => (expr.clone(), true),
  1021. Expression::AllocDynamicArray(..)
  1022. | Expression::ReturnData(_)
  1023. | Expression::Undefined(_)
  1024. | Expression::FormatString { .. }
  1025. | Expression::GetRef(..)
  1026. | Expression::InternalFunctionCfg(_) => (expr.clone(), false),
  1027. // nothing else is permitted in cfg
  1028. _ => panic!("expr should not be in cfg: {:?}", expr),
  1029. }
  1030. }
  1031. fn bigint_to_expression(loc: &Loc, ty: &Type, n: BigInt) -> (Expression, bool) {
  1032. let n = match ty {
  1033. Type::Uint(bits) => {
  1034. if n.bits() > *bits as u64 {
  1035. let (_, mut bs) = n.to_bytes_le();
  1036. bs.truncate(*bits as usize / 8);
  1037. BigInt::from_bytes_le(Sign::Plus, &bs)
  1038. } else {
  1039. n
  1040. }
  1041. }
  1042. Type::Int(bits) => {
  1043. if n.bits() > *bits as u64 {
  1044. let mut bs = n.to_signed_bytes_le();
  1045. bs.truncate(*bits as usize / 8);
  1046. BigInt::from_signed_bytes_le(&bs)
  1047. } else {
  1048. n
  1049. }
  1050. }
  1051. Type::StorageRef(..) => n,
  1052. _ => unreachable!(),
  1053. };
  1054. (Expression::NumberLiteral(*loc, ty.clone(), n), true)
  1055. }
  1056. fn get_definition<'a>(
  1057. def: &reaching_definitions::Def,
  1058. cfg: &'a ControlFlowGraph,
  1059. ) -> Option<&'a Expression> {
  1060. if let Instr::Set { expr, .. } = &cfg.blocks[def.block_no].instr[def.instr_no] {
  1061. Some(expr)
  1062. } else {
  1063. None
  1064. }
  1065. }
  1066. /// Are these two expressions the same constant-folded value?
  1067. fn constants_equal(left: &Expression, right: &Expression) -> bool {
  1068. match left {
  1069. Expression::NumberLiteral(_, _, left) => match right {
  1070. Expression::NumberLiteral(_, _, right) => left == right,
  1071. _ => false,
  1072. },
  1073. Expression::BytesLiteral(_, _, left)
  1074. | Expression::AllocDynamicArray(_, _, _, Some(left)) => match right {
  1075. Expression::BytesLiteral(_, _, right)
  1076. | Expression::AllocDynamicArray(_, _, _, Some(right)) => left == right,
  1077. _ => false,
  1078. },
  1079. _ => false,
  1080. }
  1081. }