statements.rs 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548
  1. // SPDX-License-Identifier: Apache-2.0
  2. use num_bigint::BigInt;
  3. use super::encoding::{abi_decode, abi_encode};
  4. use super::expression::{assign_single, default_gas, emit_function_call, expression};
  5. use super::Options;
  6. use super::{
  7. cfg::{ControlFlowGraph, Instr},
  8. vartable::Vartable,
  9. };
  10. use crate::codegen::constructor::call_constructor;
  11. use crate::codegen::events::new_event_emitter;
  12. use crate::codegen::unused_variable::{
  13. should_remove_assignment, should_remove_variable, SideEffectsCheckParameters,
  14. };
  15. use crate::codegen::yul::inline_assembly_cfg;
  16. use crate::codegen::Expression;
  17. use crate::sema::ast::{
  18. self, ArrayLength, CallTy, DestructureField, Function, Namespace, RetrieveType, Statement,
  19. TryCatch, Type, Type::Uint,
  20. };
  21. use crate::sema::Recurse;
  22. use num_traits::Zero;
  23. use solang_parser::pt::{self, CodeLocation, Loc::Codegen};
  24. /// Resolve a statement, which might be a block of statements or an entire body of a function
  25. pub(crate) fn statement(
  26. stmt: &Statement,
  27. func: &Function,
  28. cfg: &mut ControlFlowGraph,
  29. contract_no: usize,
  30. ns: &Namespace,
  31. vartab: &mut Vartable,
  32. loops: &mut LoopScopes,
  33. placeholder: Option<&Instr>,
  34. return_override: Option<&Instr>,
  35. opt: &Options,
  36. ) {
  37. match stmt {
  38. Statement::Block { statements, .. } => {
  39. for stmt in statements {
  40. statement(
  41. stmt,
  42. func,
  43. cfg,
  44. contract_no,
  45. ns,
  46. vartab,
  47. loops,
  48. placeholder,
  49. return_override,
  50. opt,
  51. );
  52. }
  53. }
  54. Statement::VariableDecl(loc, pos, _, Some(init)) => {
  55. if should_remove_variable(*pos, func, opt) {
  56. let mut params = SideEffectsCheckParameters {
  57. cfg,
  58. contract_no,
  59. func: Some(func),
  60. ns,
  61. vartab,
  62. opt,
  63. };
  64. //If we remove the assignment, we must keep expressions that have side effects
  65. init.recurse(&mut params, process_side_effects_expressions);
  66. return;
  67. }
  68. let mut expression = expression(init, cfg, contract_no, Some(func), ns, vartab, opt);
  69. // Let's check if the declaration is a declaration of a dynamic array
  70. if let Expression::AllocDynamicBytes {
  71. loc: loc_dyn_arr,
  72. ty: ty_dyn_arr @ Type::Array(..),
  73. size,
  74. initializer: opt,
  75. } = expression
  76. {
  77. let temp_res = vartab.temp_name("array_length", &Uint(32));
  78. cfg.add(
  79. vartab,
  80. Instr::Set {
  81. loc: *loc,
  82. res: temp_res,
  83. expr: *size,
  84. },
  85. );
  86. // If expression is an AllocDynamic array, replace the expression with AllocDynamicArray(_,_,tempvar,_) to avoid inserting size twice in the cfg
  87. expression = Expression::AllocDynamicBytes {
  88. loc: loc_dyn_arr,
  89. ty: ty_dyn_arr,
  90. size: Box::new(Expression::Variable {
  91. loc: *loc,
  92. ty: Uint(32),
  93. var_no: temp_res,
  94. }),
  95. initializer: opt,
  96. };
  97. cfg.array_lengths_temps.insert(*pos, temp_res);
  98. } else if let Expression::Variable { var_no, .. } = &expression {
  99. // If declaration happens with an existing array, check if the size of the array is known.
  100. // If the size of the right hand side is known (is in the array_length_map), make the left hand side track it
  101. // Now, we will have two keys in the map that point to the same temporary variable
  102. if let Some(to_add) = cfg.array_lengths_temps.clone().get(var_no) {
  103. cfg.array_lengths_temps.insert(*pos, *to_add);
  104. }
  105. }
  106. cfg.add(
  107. vartab,
  108. Instr::Set {
  109. loc: *loc,
  110. res: *pos,
  111. expr: expression,
  112. },
  113. );
  114. }
  115. Statement::VariableDecl(loc, pos, param, None) => {
  116. if should_remove_variable(*pos, func, opt) {
  117. return;
  118. }
  119. // Add variable as undefined
  120. cfg.add(
  121. vartab,
  122. Instr::Set {
  123. loc: *loc,
  124. res: *pos,
  125. expr: Expression::Undefined {
  126. ty: param.ty.clone(),
  127. },
  128. },
  129. );
  130. // Handling arrays without size, defaulting the initial size with zero
  131. if matches!(param.ty, Type::Array(..)) {
  132. let num = Expression::NumberLiteral {
  133. loc: Codegen,
  134. ty: Uint(32),
  135. value: BigInt::zero(),
  136. };
  137. let temp_res = vartab.temp_name("array_length", &Uint(32));
  138. cfg.add(
  139. vartab,
  140. Instr::Set {
  141. loc: *loc,
  142. res: temp_res,
  143. expr: num,
  144. },
  145. );
  146. cfg.array_lengths_temps.insert(*pos, temp_res);
  147. }
  148. }
  149. Statement::Return(_, expr) => {
  150. if let Some(return_instr) = return_override {
  151. cfg.add(vartab, return_instr.clone());
  152. } else {
  153. match expr {
  154. None => cfg.add(vartab, Instr::Return { value: Vec::new() }),
  155. Some(expr) => returns(expr, cfg, contract_no, func, ns, vartab, opt),
  156. }
  157. }
  158. }
  159. Statement::Expression(_, reachable, expr) => {
  160. if let ast::Expression::Assign { left, right, .. } = &expr {
  161. if should_remove_assignment(ns, left, func, opt) {
  162. let mut params = SideEffectsCheckParameters {
  163. cfg,
  164. contract_no,
  165. func: Some(func),
  166. ns,
  167. vartab,
  168. opt,
  169. };
  170. right.recurse(&mut params, process_side_effects_expressions);
  171. if !reachable {
  172. cfg.add(vartab, Instr::Unreachable);
  173. }
  174. return;
  175. }
  176. }
  177. let _ = expression(expr, cfg, contract_no, Some(func), ns, vartab, opt);
  178. if !reachable {
  179. cfg.add(vartab, Instr::Unreachable);
  180. }
  181. }
  182. Statement::Delete(_, ty, expr) => {
  183. let var_expr = expression(expr, cfg, contract_no, Some(func), ns, vartab, opt);
  184. cfg.add(
  185. vartab,
  186. Instr::ClearStorage {
  187. ty: ty.clone(),
  188. storage: var_expr,
  189. },
  190. );
  191. }
  192. Statement::Break(_) => {
  193. cfg.add(
  194. vartab,
  195. Instr::Branch {
  196. block: loops.do_break(),
  197. },
  198. );
  199. }
  200. Statement::Continue(_) => {
  201. cfg.add(
  202. vartab,
  203. Instr::Branch {
  204. block: loops.do_continue(),
  205. },
  206. );
  207. }
  208. Statement::If(_, _, cond, then_stmt, else_stmt) if else_stmt.is_empty() => {
  209. if_then(
  210. cond,
  211. then_stmt,
  212. func,
  213. cfg,
  214. contract_no,
  215. ns,
  216. vartab,
  217. loops,
  218. placeholder,
  219. return_override,
  220. opt,
  221. );
  222. }
  223. Statement::If(_, _, cond, then_stmt, else_stmt) => if_then_else(
  224. cond,
  225. then_stmt,
  226. else_stmt,
  227. func,
  228. cfg,
  229. contract_no,
  230. ns,
  231. vartab,
  232. loops,
  233. placeholder,
  234. return_override,
  235. opt,
  236. ),
  237. Statement::DoWhile(_, _, body_stmt, cond_expr) => {
  238. let body = cfg.new_basic_block("body".to_string());
  239. let cond = cfg.new_basic_block("conf".to_string());
  240. let end = cfg.new_basic_block("enddowhile".to_string());
  241. cfg.add(vartab, Instr::Branch { block: body });
  242. cfg.set_basic_block(body);
  243. vartab.new_dirty_tracker();
  244. loops.new_scope(end, cond);
  245. let mut body_reachable = true;
  246. for stmt in body_stmt {
  247. statement(
  248. stmt,
  249. func,
  250. cfg,
  251. contract_no,
  252. ns,
  253. vartab,
  254. loops,
  255. placeholder,
  256. return_override,
  257. opt,
  258. );
  259. body_reachable = stmt.reachable();
  260. }
  261. if body_reachable {
  262. cfg.add(vartab, Instr::Branch { block: cond });
  263. }
  264. cfg.set_basic_block(cond);
  265. let cond_expr = expression(cond_expr, cfg, contract_no, Some(func), ns, vartab, opt);
  266. cfg.add(
  267. vartab,
  268. Instr::BranchCond {
  269. cond: cond_expr,
  270. true_block: body,
  271. false_block: end,
  272. },
  273. );
  274. let set = vartab.pop_dirty_tracker();
  275. cfg.set_phis(end, set.clone());
  276. cfg.set_phis(body, set.clone());
  277. cfg.set_phis(cond, set);
  278. cfg.set_basic_block(end);
  279. }
  280. Statement::While(_, _, cond_expr, body_stmt) => {
  281. let cond = cfg.new_basic_block("cond".to_string());
  282. let body = cfg.new_basic_block("body".to_string());
  283. let end = cfg.new_basic_block("endwhile".to_string());
  284. cfg.add(vartab, Instr::Branch { block: cond });
  285. cfg.set_basic_block(cond);
  286. let cond_expr = expression(cond_expr, cfg, contract_no, Some(func), ns, vartab, opt);
  287. cfg.add(
  288. vartab,
  289. Instr::BranchCond {
  290. cond: cond_expr,
  291. true_block: body,
  292. false_block: end,
  293. },
  294. );
  295. cfg.set_basic_block(body);
  296. vartab.new_dirty_tracker();
  297. loops.new_scope(end, cond);
  298. let mut body_reachable = true;
  299. for stmt in body_stmt {
  300. statement(
  301. stmt,
  302. func,
  303. cfg,
  304. contract_no,
  305. ns,
  306. vartab,
  307. loops,
  308. placeholder,
  309. return_override,
  310. opt,
  311. );
  312. body_reachable = stmt.reachable();
  313. }
  314. if body_reachable {
  315. cfg.add(vartab, Instr::Branch { block: cond });
  316. }
  317. loops.leave_scope();
  318. let set = vartab.pop_dirty_tracker();
  319. cfg.set_phis(end, set.clone());
  320. cfg.set_phis(cond, set);
  321. cfg.set_basic_block(end);
  322. }
  323. Statement::For {
  324. init,
  325. cond: None,
  326. next,
  327. body,
  328. ..
  329. } => {
  330. let body_block = cfg.new_basic_block("body".to_string());
  331. let next_block = cfg.new_basic_block("next".to_string());
  332. let end_block = cfg.new_basic_block("endfor".to_string());
  333. for stmt in init {
  334. statement(
  335. stmt,
  336. func,
  337. cfg,
  338. contract_no,
  339. ns,
  340. vartab,
  341. loops,
  342. placeholder,
  343. return_override,
  344. opt,
  345. );
  346. }
  347. cfg.add(vartab, Instr::Branch { block: body_block });
  348. cfg.set_basic_block(body_block);
  349. loops.new_scope(
  350. end_block,
  351. if next.is_empty() {
  352. body_block
  353. } else {
  354. next_block
  355. },
  356. );
  357. vartab.new_dirty_tracker();
  358. let mut body_reachable = true;
  359. for stmt in body {
  360. statement(
  361. stmt,
  362. func,
  363. cfg,
  364. contract_no,
  365. ns,
  366. vartab,
  367. loops,
  368. placeholder,
  369. return_override,
  370. opt,
  371. );
  372. body_reachable = stmt.reachable();
  373. }
  374. if body_reachable {
  375. cfg.add(vartab, Instr::Branch { block: next_block });
  376. }
  377. loops.leave_scope();
  378. if body_reachable {
  379. cfg.set_basic_block(next_block);
  380. if !next.is_empty() {
  381. for stmt in next {
  382. statement(
  383. stmt,
  384. func,
  385. cfg,
  386. contract_no,
  387. ns,
  388. vartab,
  389. loops,
  390. placeholder,
  391. return_override,
  392. opt,
  393. );
  394. body_reachable = stmt.reachable();
  395. }
  396. }
  397. if body_reachable {
  398. cfg.add(vartab, Instr::Branch { block: body_block });
  399. }
  400. }
  401. let set = vartab.pop_dirty_tracker();
  402. cfg.set_phis(next_block, set.clone());
  403. cfg.set_phis(body_block, set.clone());
  404. cfg.set_phis(end_block, set);
  405. cfg.set_basic_block(end_block);
  406. }
  407. Statement::For {
  408. init,
  409. cond: Some(cond_expr),
  410. next,
  411. body,
  412. ..
  413. } => {
  414. let body_block = cfg.new_basic_block("body".to_string());
  415. let cond_block = cfg.new_basic_block("cond".to_string());
  416. let next_block = cfg.new_basic_block("next".to_string());
  417. let end_block = cfg.new_basic_block("endfor".to_string());
  418. for stmt in init {
  419. statement(
  420. stmt,
  421. func,
  422. cfg,
  423. contract_no,
  424. ns,
  425. vartab,
  426. loops,
  427. placeholder,
  428. return_override,
  429. opt,
  430. );
  431. }
  432. cfg.add(vartab, Instr::Branch { block: cond_block });
  433. cfg.set_basic_block(cond_block);
  434. let cond_expr = expression(cond_expr, cfg, contract_no, Some(func), ns, vartab, opt);
  435. cfg.add(
  436. vartab,
  437. Instr::BranchCond {
  438. cond: cond_expr,
  439. true_block: body_block,
  440. false_block: end_block,
  441. },
  442. );
  443. cfg.set_basic_block(body_block);
  444. // continue goes to next
  445. loops.new_scope(end_block, next_block);
  446. vartab.new_dirty_tracker();
  447. let mut body_reachable = true;
  448. for stmt in body {
  449. statement(
  450. stmt,
  451. func,
  452. cfg,
  453. contract_no,
  454. ns,
  455. vartab,
  456. loops,
  457. placeholder,
  458. return_override,
  459. opt,
  460. );
  461. body_reachable = stmt.reachable();
  462. }
  463. if body_reachable {
  464. cfg.add(vartab, Instr::Branch { block: next_block });
  465. }
  466. loops.leave_scope();
  467. cfg.set_basic_block(next_block);
  468. let mut next_reachable = true;
  469. for stmt in next {
  470. statement(
  471. stmt,
  472. func,
  473. cfg,
  474. contract_no,
  475. ns,
  476. vartab,
  477. loops,
  478. placeholder,
  479. return_override,
  480. opt,
  481. );
  482. next_reachable = stmt.reachable();
  483. }
  484. if next_reachable {
  485. cfg.add(vartab, Instr::Branch { block: cond_block });
  486. }
  487. cfg.set_basic_block(end_block);
  488. let set = vartab.pop_dirty_tracker();
  489. cfg.set_phis(next_block, set.clone());
  490. cfg.set_phis(end_block, set.clone());
  491. cfg.set_phis(cond_block, set);
  492. }
  493. Statement::Destructure(_, fields, expr) => {
  494. destructure(fields, expr, cfg, contract_no, func, ns, vartab, opt)
  495. }
  496. Statement::TryCatch(_, _, try_stmt) => try_catch(
  497. try_stmt,
  498. func,
  499. cfg,
  500. contract_no,
  501. ns,
  502. vartab,
  503. loops,
  504. placeholder,
  505. return_override,
  506. opt,
  507. ),
  508. Statement::Emit {
  509. loc,
  510. event_no,
  511. args,
  512. ..
  513. } => {
  514. let emitter = new_event_emitter(loc, *event_no, args, ns);
  515. emitter.emit(contract_no, func, cfg, vartab, opt);
  516. }
  517. Statement::Underscore(_) => {
  518. // ensure we get phi nodes for the return values
  519. if let Some(instr @ Instr::Call { res, .. }) = placeholder {
  520. for var_no in res {
  521. vartab.set_dirty(*var_no);
  522. }
  523. cfg.add(vartab, instr.clone());
  524. } else {
  525. panic!("placeholder should be provided for modifiers");
  526. }
  527. }
  528. Statement::Assembly(inline_assembly, ..) => {
  529. inline_assembly_cfg(inline_assembly, contract_no, ns, cfg, vartab, opt);
  530. }
  531. }
  532. }
  533. /// Generate if-then-no-else
  534. fn if_then(
  535. cond: &ast::Expression,
  536. then_stmt: &[Statement],
  537. func: &Function,
  538. cfg: &mut ControlFlowGraph,
  539. contract_no: usize,
  540. ns: &Namespace,
  541. vartab: &mut Vartable,
  542. loops: &mut LoopScopes,
  543. placeholder: Option<&Instr>,
  544. return_override: Option<&Instr>,
  545. opt: &Options,
  546. ) {
  547. let cond = expression(cond, cfg, contract_no, Some(func), ns, vartab, opt);
  548. let then = cfg.new_basic_block("then".to_string());
  549. let endif = cfg.new_basic_block("endif".to_string());
  550. cfg.add(
  551. vartab,
  552. Instr::BranchCond {
  553. cond,
  554. true_block: then,
  555. false_block: endif,
  556. },
  557. );
  558. cfg.set_basic_block(then);
  559. vartab.new_dirty_tracker();
  560. let mut reachable = true;
  561. for stmt in then_stmt {
  562. statement(
  563. stmt,
  564. func,
  565. cfg,
  566. contract_no,
  567. ns,
  568. vartab,
  569. loops,
  570. placeholder,
  571. return_override,
  572. opt,
  573. );
  574. reachable = stmt.reachable();
  575. }
  576. if reachable {
  577. cfg.add(vartab, Instr::Branch { block: endif });
  578. }
  579. cfg.set_phis(endif, vartab.pop_dirty_tracker());
  580. cfg.set_basic_block(endif);
  581. }
  582. /// Generate if-then-else
  583. fn if_then_else(
  584. cond: &ast::Expression,
  585. then_stmt: &[Statement],
  586. else_stmt: &[Statement],
  587. func: &Function,
  588. cfg: &mut ControlFlowGraph,
  589. contract_no: usize,
  590. ns: &Namespace,
  591. vartab: &mut Vartable,
  592. loops: &mut LoopScopes,
  593. placeholder: Option<&Instr>,
  594. return_override: Option<&Instr>,
  595. opt: &Options,
  596. ) {
  597. let cond = expression(cond, cfg, contract_no, Some(func), ns, vartab, opt);
  598. let then = cfg.new_basic_block("then".to_string());
  599. let else_ = cfg.new_basic_block("else".to_string());
  600. let endif = cfg.new_basic_block("endif".to_string());
  601. cfg.add(
  602. vartab,
  603. Instr::BranchCond {
  604. cond,
  605. true_block: then,
  606. false_block: else_,
  607. },
  608. );
  609. // then
  610. cfg.set_basic_block(then);
  611. vartab.new_dirty_tracker();
  612. let mut then_reachable = true;
  613. for stmt in then_stmt {
  614. statement(
  615. stmt,
  616. func,
  617. cfg,
  618. contract_no,
  619. ns,
  620. vartab,
  621. loops,
  622. placeholder,
  623. return_override,
  624. opt,
  625. );
  626. then_reachable = stmt.reachable();
  627. }
  628. if then_reachable {
  629. cfg.add(vartab, Instr::Branch { block: endif });
  630. }
  631. // else
  632. cfg.set_basic_block(else_);
  633. let mut else_reachable = true;
  634. for stmt in else_stmt {
  635. statement(
  636. stmt,
  637. func,
  638. cfg,
  639. contract_no,
  640. ns,
  641. vartab,
  642. loops,
  643. placeholder,
  644. return_override,
  645. opt,
  646. );
  647. else_reachable = stmt.reachable();
  648. }
  649. if else_reachable {
  650. cfg.add(vartab, Instr::Branch { block: endif });
  651. }
  652. cfg.set_phis(endif, vartab.pop_dirty_tracker());
  653. cfg.set_basic_block(endif);
  654. }
  655. fn returns(
  656. expr: &ast::Expression,
  657. cfg: &mut ControlFlowGraph,
  658. contract_no: usize,
  659. func: &Function,
  660. ns: &Namespace,
  661. vartab: &mut Vartable,
  662. opt: &Options,
  663. ) {
  664. // Can only be another function call without returns
  665. let uncast_values = match expr {
  666. // Explicitly recurse for conditinal operator expressions.
  667. // `return a ? b : c` is transformed into pseudo code `a ? return b : return c`
  668. ast::Expression::ConditionalOperator {
  669. cond,
  670. true_option: left,
  671. false_option: right,
  672. ..
  673. } => {
  674. let cond = expression(cond, cfg, contract_no, Some(func), ns, vartab, opt);
  675. let left_block = cfg.new_basic_block("left".to_string());
  676. let right_block = cfg.new_basic_block("right".to_string());
  677. cfg.add(
  678. vartab,
  679. Instr::BranchCond {
  680. cond,
  681. true_block: left_block,
  682. false_block: right_block,
  683. },
  684. );
  685. vartab.new_dirty_tracker();
  686. cfg.set_basic_block(left_block);
  687. returns(left, cfg, contract_no, func, ns, vartab, opt);
  688. cfg.set_basic_block(right_block);
  689. returns(right, cfg, contract_no, func, ns, vartab, opt);
  690. return;
  691. }
  692. ast::Expression::Builtin {
  693. kind: ast::Builtin::AbiDecode,
  694. ..
  695. }
  696. | ast::Expression::InternalFunctionCall { .. }
  697. | ast::Expression::ExternalFunctionCall { .. }
  698. | ast::Expression::ExternalFunctionCallRaw { .. } => {
  699. emit_function_call(expr, contract_no, cfg, Some(func), ns, vartab, opt)
  700. }
  701. ast::Expression::List { list, .. } => list
  702. .iter()
  703. .map(|e| expression(e, cfg, contract_no, Some(func), ns, vartab, opt))
  704. .collect::<Vec<Expression>>(),
  705. // Can be any other expression
  706. _ => {
  707. vec![expression(
  708. expr,
  709. cfg,
  710. contract_no,
  711. Some(func),
  712. ns,
  713. vartab,
  714. opt,
  715. )]
  716. }
  717. };
  718. let cast_values = func
  719. .returns
  720. .iter()
  721. .zip(uncast_values.into_iter())
  722. .map(|(left, right)| try_load_and_cast(&right.loc(), &right, &left.ty, ns, cfg, vartab))
  723. .collect();
  724. cfg.add(vartab, Instr::Return { value: cast_values });
  725. }
  726. fn destructure(
  727. fields: &[DestructureField],
  728. expr: &ast::Expression,
  729. cfg: &mut ControlFlowGraph,
  730. contract_no: usize,
  731. func: &Function,
  732. ns: &Namespace,
  733. vartab: &mut Vartable,
  734. opt: &Options,
  735. ) {
  736. if let ast::Expression::ConditionalOperator {
  737. cond,
  738. true_option: left,
  739. false_option: right,
  740. ..
  741. } = expr
  742. {
  743. let cond = expression(cond, cfg, contract_no, Some(func), ns, vartab, opt);
  744. let left_block = cfg.new_basic_block("left".to_string());
  745. let right_block = cfg.new_basic_block("right".to_string());
  746. let done_block = cfg.new_basic_block("done".to_string());
  747. cfg.add(
  748. vartab,
  749. Instr::BranchCond {
  750. cond,
  751. true_block: left_block,
  752. false_block: right_block,
  753. },
  754. );
  755. vartab.new_dirty_tracker();
  756. cfg.set_basic_block(left_block);
  757. destructure(fields, left, cfg, contract_no, func, ns, vartab, opt);
  758. cfg.add(vartab, Instr::Branch { block: done_block });
  759. cfg.set_basic_block(right_block);
  760. destructure(fields, right, cfg, contract_no, func, ns, vartab, opt);
  761. cfg.add(vartab, Instr::Branch { block: done_block });
  762. cfg.set_phis(done_block, vartab.pop_dirty_tracker());
  763. cfg.set_basic_block(done_block);
  764. return;
  765. }
  766. let mut values = match expr {
  767. ast::Expression::List { list, .. } => {
  768. let mut values = Vec::new();
  769. for expr in list {
  770. let loc = expr.loc();
  771. let expr = expression(expr, cfg, contract_no, Some(func), ns, vartab, opt);
  772. let ty = expr.ty();
  773. let res = vartab.temp_anonymous(&ty);
  774. cfg.add(vartab, Instr::Set { loc, res, expr });
  775. values.push(Expression::Variable {
  776. loc,
  777. ty,
  778. var_no: res,
  779. });
  780. }
  781. values
  782. }
  783. _ => {
  784. // must be function call, either internal or external
  785. emit_function_call(expr, contract_no, cfg, Some(func), ns, vartab, opt)
  786. }
  787. };
  788. for field in fields.iter() {
  789. let right = values.remove(0);
  790. match field {
  791. DestructureField::None => {
  792. // nothing to do
  793. }
  794. DestructureField::VariableDecl(res, param) => {
  795. let expr = try_load_and_cast(&param.loc, &right, &param.ty, ns, cfg, vartab);
  796. if should_remove_variable(*res, func, opt) {
  797. continue;
  798. }
  799. cfg.add(
  800. vartab,
  801. Instr::Set {
  802. loc: param.loc,
  803. res: *res,
  804. expr,
  805. },
  806. );
  807. }
  808. DestructureField::Expression(left) => {
  809. let expr = try_load_and_cast(&left.loc(), &right, &left.ty(), ns, cfg, vartab);
  810. if should_remove_assignment(ns, left, func, opt) {
  811. continue;
  812. }
  813. assign_single(left, expr, cfg, contract_no, Some(func), ns, vartab, opt);
  814. }
  815. }
  816. }
  817. }
  818. /// During a destructure statement, sema only checks if the cast is possible. During codegen, we
  819. /// perform the real cast and add an instruction to the CFG to load a value from the storage if want it.
  820. /// The existing codegen cast function does not manage the CFG, so the loads must be done here.
  821. fn try_load_and_cast(
  822. loc: &pt::Loc,
  823. expr: &Expression,
  824. to_ty: &Type,
  825. ns: &Namespace,
  826. cfg: &mut ControlFlowGraph,
  827. vartab: &mut Vartable,
  828. ) -> Expression {
  829. match expr.ty() {
  830. Type::StorageRef(_, ty) => {
  831. if let Expression::Subscript { array_ty, .. } = &expr {
  832. if array_ty.is_storage_bytes() {
  833. return expr.cast(to_ty, ns);
  834. }
  835. }
  836. if matches!(to_ty, Type::StorageRef(..)) {
  837. // If we want a storage reference, there is no need to load from storage
  838. return expr.cast(to_ty, ns);
  839. }
  840. let anonymous_no = vartab.temp_anonymous(&ty);
  841. cfg.add(
  842. vartab,
  843. Instr::LoadStorage {
  844. res: anonymous_no,
  845. ty: (*ty).clone(),
  846. storage: expr.cast(to_ty, ns),
  847. },
  848. );
  849. Expression::Variable {
  850. loc: *loc,
  851. ty: (*ty).clone(),
  852. var_no: anonymous_no,
  853. }
  854. }
  855. Type::Ref(ty) => match *ty {
  856. Type::Array(_, _) => expr.cast(to_ty, ns),
  857. _ => Expression::Load {
  858. loc: pt::Loc::Builtin,
  859. ty: *ty,
  860. expr: expr.clone().into(),
  861. }
  862. .cast(to_ty, ns),
  863. },
  864. _ => expr.cast(to_ty, ns),
  865. }
  866. }
  867. /// Resolve try catch statement
  868. fn try_catch(
  869. try_stmt: &TryCatch,
  870. func: &Function,
  871. cfg: &mut ControlFlowGraph,
  872. callee_contract_no: usize,
  873. ns: &Namespace,
  874. vartab: &mut Vartable,
  875. loops: &mut LoopScopes,
  876. placeholder: Option<&Instr>,
  877. return_override: Option<&Instr>,
  878. opt: &Options,
  879. ) {
  880. let success = vartab.temp(
  881. &pt::Identifier {
  882. loc: try_stmt.expr.loc(),
  883. name: "success".to_owned(),
  884. },
  885. &Type::Bool,
  886. );
  887. let success_block = cfg.new_basic_block("success".to_string());
  888. let catch_block = cfg.new_basic_block("catch".to_string());
  889. let finally_block = cfg.new_basic_block("finally".to_string());
  890. match &try_stmt.expr {
  891. ast::Expression::ExternalFunctionCall {
  892. loc,
  893. function,
  894. args,
  895. call_args,
  896. ..
  897. } => {
  898. if let Type::ExternalFunction {
  899. returns: func_returns,
  900. ..
  901. } = function.ty()
  902. {
  903. let value = if let Some(value) = &call_args.value {
  904. expression(value, cfg, callee_contract_no, Some(func), ns, vartab, opt)
  905. } else {
  906. Expression::NumberLiteral {
  907. loc: Codegen,
  908. ty: Type::Value,
  909. value: BigInt::zero(),
  910. }
  911. };
  912. let gas = if let Some(gas) = &call_args.gas {
  913. expression(gas, cfg, callee_contract_no, Some(func), ns, vartab, opt)
  914. } else {
  915. default_gas(ns)
  916. };
  917. let function = expression(
  918. function,
  919. cfg,
  920. callee_contract_no,
  921. Some(func),
  922. ns,
  923. vartab,
  924. opt,
  925. );
  926. let mut args = args
  927. .iter()
  928. .map(|a| expression(a, cfg, callee_contract_no, Some(func), ns, vartab, opt))
  929. .collect::<Vec<Expression>>();
  930. let selector = function.external_function_selector();
  931. let address = function.external_function_address();
  932. args.insert(0, selector);
  933. let (payload, _) = abi_encode(loc, args, ns, vartab, cfg, false);
  934. cfg.add(
  935. vartab,
  936. Instr::ExternalCall {
  937. success: Some(success),
  938. address: Some(address),
  939. accounts: None,
  940. seeds: None,
  941. payload,
  942. value,
  943. gas,
  944. callty: CallTy::Regular,
  945. contract_function_no: None,
  946. },
  947. );
  948. cfg.add(
  949. vartab,
  950. Instr::BranchCond {
  951. cond: Expression::Variable {
  952. loc: try_stmt.expr.loc(),
  953. ty: Type::Bool,
  954. var_no: success,
  955. },
  956. true_block: success_block,
  957. false_block: catch_block,
  958. },
  959. );
  960. cfg.set_basic_block(success_block);
  961. if func_returns != vec![Type::Void] {
  962. let mut res = Vec::new();
  963. for ret in &try_stmt.returns {
  964. res.push(match ret {
  965. (Some(pos), _) => *pos,
  966. (None, param) => vartab.temp_anonymous(&param.ty),
  967. });
  968. }
  969. let buf = &Expression::ReturnData { loc: Codegen };
  970. let decoded = abi_decode(&Codegen, buf, &func_returns, ns, vartab, cfg, None);
  971. for instruction in res.iter().zip(decoded).map(|(var, expr)| Instr::Set {
  972. loc: Codegen,
  973. res: *var,
  974. expr,
  975. }) {
  976. cfg.add(vartab, instruction)
  977. }
  978. }
  979. } else {
  980. // dynamic dispatch
  981. unimplemented!();
  982. }
  983. }
  984. ast::Expression::Constructor {
  985. loc,
  986. contract_no,
  987. constructor_no,
  988. args,
  989. call_args,
  990. ..
  991. } => {
  992. let address_res = match try_stmt.returns.get(0) {
  993. Some((Some(pos), _)) => *pos,
  994. _ => vartab.temp_anonymous(&Type::Contract(*contract_no)),
  995. };
  996. call_constructor(
  997. loc,
  998. *contract_no,
  999. callee_contract_no,
  1000. constructor_no,
  1001. args,
  1002. call_args,
  1003. address_res,
  1004. Some(success),
  1005. Some(func),
  1006. ns,
  1007. vartab,
  1008. cfg,
  1009. opt,
  1010. );
  1011. cfg.add(
  1012. vartab,
  1013. Instr::BranchCond {
  1014. cond: Expression::Variable {
  1015. loc: try_stmt.expr.loc(),
  1016. ty: Type::Bool,
  1017. var_no: success,
  1018. },
  1019. true_block: success_block,
  1020. false_block: catch_block,
  1021. },
  1022. );
  1023. cfg.set_basic_block(success_block);
  1024. }
  1025. _ => unreachable!(),
  1026. }
  1027. vartab.new_dirty_tracker();
  1028. let mut finally_reachable = true;
  1029. for stmt in &try_stmt.ok_stmt {
  1030. statement(
  1031. stmt,
  1032. func,
  1033. cfg,
  1034. callee_contract_no,
  1035. ns,
  1036. vartab,
  1037. loops,
  1038. placeholder,
  1039. return_override,
  1040. opt,
  1041. );
  1042. finally_reachable = stmt.reachable();
  1043. }
  1044. if finally_reachable {
  1045. cfg.add(
  1046. vartab,
  1047. Instr::Branch {
  1048. block: finally_block,
  1049. },
  1050. );
  1051. }
  1052. cfg.set_basic_block(catch_block);
  1053. for (error_param_pos, error_param, error_stmt) in &try_stmt.errors {
  1054. let no_reason_block = cfg.new_basic_block("no_reason".to_string());
  1055. let error_var = match error_param_pos {
  1056. Some(pos) => *pos,
  1057. _ => vartab.temp_anonymous(&Type::String),
  1058. };
  1059. // Expect the returned data to match the 4 bytes function selector for "Error(string)"
  1060. let buf = &Expression::ReturnData { loc: Codegen };
  1061. let tys = &[Uint(32), error_param.ty.clone()];
  1062. let decoded = abi_decode(&Codegen, buf, tys, ns, vartab, cfg, None);
  1063. let err_id = Expression::NumberLiteral {
  1064. loc: Codegen,
  1065. ty: Uint(32),
  1066. value: 0x08c3_79a0.into(),
  1067. }
  1068. .into();
  1069. let cond = Expression::Equal {
  1070. loc: Codegen,
  1071. left: decoded[0].clone().into(),
  1072. right: err_id,
  1073. };
  1074. let match_err_id = cfg.new_basic_block("match_err_id".into());
  1075. let no_match_err_id = cfg.new_basic_block("no_match_err_id".into());
  1076. let instruction = Instr::BranchCond {
  1077. cond,
  1078. true_block: match_err_id,
  1079. false_block: no_match_err_id,
  1080. };
  1081. cfg.add(vartab, instruction);
  1082. cfg.set_basic_block(no_match_err_id);
  1083. cfg.add(vartab, Instr::AssertFailure { encoded_args: None });
  1084. cfg.set_basic_block(match_err_id);
  1085. let instruction = Instr::Set {
  1086. loc: Codegen,
  1087. res: error_var,
  1088. expr: decoded[1].clone(),
  1089. };
  1090. cfg.add(vartab, instruction);
  1091. let mut reachable = true;
  1092. for stmt in error_stmt {
  1093. statement(
  1094. stmt,
  1095. func,
  1096. cfg,
  1097. callee_contract_no,
  1098. ns,
  1099. vartab,
  1100. loops,
  1101. placeholder,
  1102. return_override,
  1103. opt,
  1104. );
  1105. reachable = stmt.reachable();
  1106. }
  1107. if reachable {
  1108. cfg.add(
  1109. vartab,
  1110. Instr::Branch {
  1111. block: finally_block,
  1112. },
  1113. );
  1114. }
  1115. cfg.set_basic_block(no_reason_block);
  1116. }
  1117. if let Some(res) = try_stmt.catch_param_pos {
  1118. let instruction = Instr::Set {
  1119. loc: Codegen,
  1120. res,
  1121. expr: Expression::ReturnData { loc: Codegen },
  1122. };
  1123. cfg.add(vartab, instruction);
  1124. }
  1125. let mut reachable = true;
  1126. for stmt in &try_stmt.catch_stmt {
  1127. statement(
  1128. stmt,
  1129. func,
  1130. cfg,
  1131. callee_contract_no,
  1132. ns,
  1133. vartab,
  1134. loops,
  1135. placeholder,
  1136. return_override,
  1137. opt,
  1138. );
  1139. reachable = stmt.reachable();
  1140. }
  1141. if reachable {
  1142. cfg.add(
  1143. vartab,
  1144. Instr::Branch {
  1145. block: finally_block,
  1146. },
  1147. );
  1148. }
  1149. let mut set = vartab.pop_dirty_tracker();
  1150. if let Some(pos) = &try_stmt.catch_param_pos {
  1151. set.remove(pos);
  1152. }
  1153. for (pos, _, _) in &try_stmt.errors {
  1154. if let Some(pos) = pos {
  1155. set.remove(pos);
  1156. }
  1157. }
  1158. cfg.set_phis(finally_block, set);
  1159. cfg.set_basic_block(finally_block);
  1160. }
  1161. pub struct LoopScope {
  1162. break_bb: usize,
  1163. continue_bb: usize,
  1164. }
  1165. pub struct LoopScopes(Vec<LoopScope>);
  1166. impl LoopScopes {
  1167. pub fn new() -> Self {
  1168. LoopScopes(Vec::new())
  1169. }
  1170. pub(crate) fn new_scope(&mut self, break_bb: usize, continue_bb: usize) {
  1171. self.0.push(LoopScope {
  1172. break_bb,
  1173. continue_bb,
  1174. })
  1175. }
  1176. pub(crate) fn leave_scope(&mut self) -> LoopScope {
  1177. self.0.pop().expect("should be in loop scope")
  1178. }
  1179. pub(crate) fn do_break(&mut self) -> usize {
  1180. self.0.last().unwrap().break_bb
  1181. }
  1182. pub(crate) fn do_continue(&mut self) -> usize {
  1183. self.0.last().unwrap().continue_bb
  1184. }
  1185. }
  1186. impl Type {
  1187. /// Default value for a type, e.g. an empty string. Some types cannot have a default value,
  1188. /// for example a reference to a variable in storage.
  1189. pub fn default(&self, ns: &Namespace) -> Option<Expression> {
  1190. match self {
  1191. Type::Address(_) | Uint(_) | Type::Int(_) => Some(Expression::NumberLiteral {
  1192. loc: Codegen,
  1193. ty: self.clone(),
  1194. value: BigInt::from(0),
  1195. }),
  1196. Type::Bool => Some(Expression::BoolLiteral {
  1197. loc: Codegen,
  1198. value: false,
  1199. }),
  1200. Type::Bytes(n) => {
  1201. let mut l = Vec::new();
  1202. l.resize(*n as usize, 0);
  1203. Some(Expression::BytesLiteral {
  1204. loc: Codegen,
  1205. ty: self.clone(),
  1206. value: l,
  1207. })
  1208. }
  1209. Type::Enum(e) => ns.enums[*e].ty.default(ns),
  1210. Type::Struct(struct_ty) => {
  1211. // make sure all our fields have default values
  1212. for field in &struct_ty.definition(ns).fields {
  1213. field.ty.default(ns)?;
  1214. }
  1215. Some(Expression::StructLiteral {
  1216. loc: Codegen,
  1217. ty: self.clone(),
  1218. values: Vec::new(),
  1219. })
  1220. }
  1221. Type::Ref(ty) => {
  1222. assert!(matches!(ty.as_ref(), Type::Address(_)));
  1223. Some(Expression::GetRef {
  1224. loc: Codegen,
  1225. ty: Type::Ref(Box::new(ty.as_ref().clone())),
  1226. expr: Box::new(Expression::NumberLiteral {
  1227. loc: Codegen,
  1228. ty: ty.as_ref().clone(),
  1229. value: BigInt::from(0),
  1230. }),
  1231. })
  1232. }
  1233. Type::StorageRef(..) => None,
  1234. Type::String | Type::DynamicBytes => Some(Expression::AllocDynamicBytes {
  1235. loc: Codegen,
  1236. ty: self.clone(),
  1237. size: Box::new(Expression::NumberLiteral {
  1238. loc: Codegen,
  1239. ty: Uint(32),
  1240. value: BigInt::zero(),
  1241. }),
  1242. initializer: None,
  1243. }),
  1244. Type::InternalFunction { .. } | Type::Contract(_) | Type::ExternalFunction { .. } => {
  1245. None
  1246. }
  1247. Type::Array(ty, dims) => {
  1248. ty.default(ns)?;
  1249. if dims.last() == Some(&ArrayLength::Dynamic) {
  1250. Some(Expression::AllocDynamicBytes {
  1251. loc: Codegen,
  1252. ty: self.clone(),
  1253. size: Box::new(Expression::NumberLiteral {
  1254. loc: Codegen,
  1255. ty: Uint(32),
  1256. value: BigInt::zero(),
  1257. }),
  1258. initializer: None,
  1259. })
  1260. } else {
  1261. Some(Expression::ArrayLiteral {
  1262. loc: Codegen,
  1263. ty: self.clone(),
  1264. dimensions: Vec::new(),
  1265. values: Vec::new(),
  1266. })
  1267. }
  1268. }
  1269. _ => None,
  1270. }
  1271. }
  1272. }
  1273. impl Namespace {
  1274. /// Phoney default constructor
  1275. pub fn default_constructor(&self, contract_no: usize) -> Function {
  1276. let mut func = Function::new(
  1277. Codegen,
  1278. "".to_owned(),
  1279. Some(contract_no),
  1280. vec![],
  1281. pt::FunctionTy::Constructor,
  1282. None,
  1283. pt::Visibility::Public(None),
  1284. Vec::new(),
  1285. Vec::new(),
  1286. self,
  1287. );
  1288. func.body = vec![Statement::Return(Codegen, None)];
  1289. func.has_body = true;
  1290. func
  1291. }
  1292. }
  1293. /// This function looks for expressions that have side effects during code execution and
  1294. /// processes them.
  1295. /// They must be added to the cfg event if we remove the assignment
  1296. pub fn process_side_effects_expressions(
  1297. exp: &ast::Expression,
  1298. ctx: &mut SideEffectsCheckParameters,
  1299. ) -> bool {
  1300. match &exp {
  1301. ast::Expression::InternalFunctionCall { .. }
  1302. | ast::Expression::ExternalFunctionCall { .. }
  1303. | ast::Expression::ExternalFunctionCallRaw { .. }
  1304. | ast::Expression::Constructor { .. }
  1305. | ast::Expression::Assign { .. } => {
  1306. let _ = expression(
  1307. exp,
  1308. ctx.cfg,
  1309. ctx.contract_no,
  1310. ctx.func,
  1311. ctx.ns,
  1312. ctx.vartab,
  1313. ctx.opt,
  1314. );
  1315. false
  1316. }
  1317. ast::Expression::Builtin {
  1318. kind: builtin_type, ..
  1319. } => match &builtin_type {
  1320. ast::Builtin::PayableSend
  1321. | ast::Builtin::ArrayPush
  1322. | ast::Builtin::ArrayPop
  1323. // PayableTransfer, Revert, Require and SelfDestruct do not occur inside an expression
  1324. // for they return no value. They should not bother the unused variable elimination.
  1325. | ast::Builtin::PayableTransfer
  1326. | ast::Builtin::Revert
  1327. | ast::Builtin::Require
  1328. | ast::Builtin::SelfDestruct
  1329. | ast::Builtin::WriteInt8
  1330. | ast::Builtin::WriteInt16LE
  1331. | ast::Builtin::WriteInt32LE
  1332. | ast::Builtin::WriteInt64LE
  1333. | ast::Builtin::WriteInt128LE
  1334. | ast::Builtin::WriteInt256LE
  1335. | ast::Builtin::WriteUint16LE
  1336. | ast::Builtin::WriteUint32LE
  1337. | ast::Builtin::WriteUint64LE
  1338. | ast::Builtin::WriteUint128LE
  1339. | ast::Builtin::WriteUint256LE
  1340. | ast::Builtin::WriteAddress => {
  1341. let _ = expression(exp, ctx.cfg, ctx.contract_no, ctx.func, ctx.ns, ctx.vartab, ctx.opt);
  1342. false
  1343. }
  1344. _ => true,
  1345. },
  1346. _ => true,
  1347. }
  1348. }