array_boundary.rs 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. // SPDX-License-Identifier: Apache-2.0
  2. use super::vartable::Vartable;
  3. use crate::codegen::cfg::{ControlFlowGraph, Instr};
  4. use crate::codegen::Expression;
  5. use crate::sema::ast::Type;
  6. use solang_parser::pt::Loc;
  7. /// This function is called whenever an assignment statement of an array is encountered. We have to ensure
  8. /// that the variable number of the array is tied to the variable number of the correct temporary variable.
  9. /// We have two cases:
  10. /// Case 1: If the right hand side is an array, the left array keeps track of the temp variable of the right array (if a temp variable exists)
  11. /// Case 2: If reallocation of the left array is done (with a new expression), we create a new temp variable and the left side tracks it.
  12. /// If that's the case, we return an AllocDynamicArray expression with the size being the temp variable to avoid repetitive expressions in the cfg.
  13. pub(crate) fn handle_array_assign(
  14. right: Expression,
  15. cfg: &mut ControlFlowGraph,
  16. vartab: &mut Vartable,
  17. pos: &usize,
  18. ) -> Expression {
  19. if let Expression::AllocDynamicArray(loc, ty @ Type::Array(..), size, option) = right {
  20. // If we re-allocate the pointer, create a new temp variable to hold the new array length
  21. let temp_res = vartab.temp_name("array_length", &Type::Uint(32));
  22. cfg.add(
  23. vartab,
  24. Instr::Set {
  25. loc: Loc::Codegen,
  26. res: temp_res,
  27. expr: *size,
  28. },
  29. );
  30. cfg.array_lengths_temps.insert(*pos, temp_res);
  31. Expression::AllocDynamicArray(
  32. loc,
  33. ty,
  34. Box::new(Expression::Variable(Loc::Codegen, Type::Uint(32), temp_res)),
  35. option,
  36. )
  37. } else {
  38. if let Expression::Variable(_, _, right_res) = &right {
  39. // If we have initialized a temp var for this var
  40. if cfg.array_lengths_temps.contains_key(right_res) {
  41. let to_update = cfg.array_lengths_temps[right_res];
  42. cfg.array_lengths_temps.insert(*pos, to_update);
  43. } else {
  44. // If the right hand side doesn't have a temp, it must be a function parameter or a struct member.
  45. cfg.array_lengths_temps.remove(pos);
  46. }
  47. }
  48. right.clone()
  49. }
  50. }