mod.rs 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. // SPDX-License-Identifier: Apache-2.0
  2. use crate::codegen::cfg::{
  3. optimize_and_check_cfg, populate_arguments, populate_named_returns, ASTFunction,
  4. ControlFlowGraph, Instr,
  5. };
  6. use crate::codegen::statements::LoopScopes;
  7. use crate::codegen::vartable::Vartable;
  8. use crate::codegen::yul::statements::statement;
  9. use crate::codegen::{Expression, Options};
  10. use crate::sema::ast::Namespace;
  11. use crate::sema::yul::ast::InlineAssembly;
  12. use solang_parser::pt;
  13. use solang_parser::pt::FunctionTy;
  14. mod builtin;
  15. mod expression;
  16. mod statements;
  17. mod tests;
  18. /// Create the CFG instructions for inline assembly statements
  19. pub fn inline_assembly_cfg(
  20. inline_assembly: &InlineAssembly,
  21. contract_no: usize,
  22. ns: &Namespace,
  23. cfg: &mut ControlFlowGraph,
  24. vartab: &mut Vartable,
  25. opt: &Options,
  26. ) {
  27. let mut loops = LoopScopes::new();
  28. for stmt in &inline_assembly.body {
  29. statement(stmt, contract_no, &mut loops, ns, cfg, vartab, &None, opt);
  30. }
  31. }
  32. /// Create the CFG for yul functions
  33. pub(crate) fn generate_yul_function_cfg(
  34. contract_no: usize,
  35. function_no: usize,
  36. all_cfgs: &mut [ControlFlowGraph],
  37. ns: &mut Namespace,
  38. opt: &Options,
  39. ) {
  40. let mut cfg = yul_function_cfg(contract_no, function_no, ns, opt);
  41. optimize_and_check_cfg(&mut cfg, ns, ASTFunction::YulFunction(function_no), opt);
  42. all_cfgs[ns.yul_functions[function_no].cfg_no] = cfg;
  43. }
  44. /// Generate the CFG containing all the instructions from a YUL function
  45. fn yul_function_cfg(
  46. contract_no: usize,
  47. function_no: usize,
  48. ns: &mut Namespace,
  49. opt: &Options,
  50. ) -> ControlFlowGraph {
  51. let mut vartab =
  52. Vartable::from_symbol_table(&ns.yul_functions[function_no].symtable, ns.next_id);
  53. let mut loops = LoopScopes::new();
  54. let yul_func = &ns.yul_functions[function_no];
  55. let func_name = format!(
  56. "{}::yul_function_{}::{}",
  57. ns.contracts[contract_no].name, function_no, yul_func.name
  58. );
  59. let mut cfg = ControlFlowGraph::new(func_name, ASTFunction::YulFunction(function_no));
  60. cfg.params = yul_func.params.clone();
  61. cfg.returns = yul_func.returns.clone();
  62. cfg.selector = Vec::new();
  63. cfg.public = false;
  64. cfg.ty = FunctionTy::Function;
  65. cfg.nonpayable = true;
  66. // populate the arguments
  67. populate_arguments(yul_func, &mut cfg, &mut vartab);
  68. // populate the returns, if any
  69. populate_named_returns(yul_func, ns, &mut cfg, &mut vartab);
  70. let returns = if yul_func.returns.is_empty() {
  71. Instr::Return { value: vec![] }
  72. } else {
  73. Instr::Return {
  74. value: yul_func
  75. .symtable
  76. .returns
  77. .iter()
  78. .map(|pos| Expression::Variable {
  79. loc: pt::Loc::Codegen,
  80. ty: yul_func.symtable.vars[pos].ty.clone(),
  81. var_no: *pos,
  82. })
  83. .collect::<Vec<Expression>>(),
  84. }
  85. };
  86. for stmt in &yul_func.body {
  87. statement(
  88. stmt,
  89. contract_no,
  90. &mut loops,
  91. ns,
  92. &mut cfg,
  93. &mut vartab,
  94. &Some(returns.clone()),
  95. opt,
  96. );
  97. }
  98. if yul_func.body.is_empty()
  99. || (!yul_func.body.is_empty() && yul_func.body.last().unwrap().is_reachable())
  100. {
  101. cfg.add(&mut vartab, returns);
  102. }
  103. vartab.finalize(ns, &mut cfg);
  104. cfg
  105. }