// SPDX-License-Identifier: Apache-2.0 use super::vartable::Vartable; use crate::codegen::cfg::{ControlFlowGraph, Instr}; use crate::codegen::Expression; use crate::sema::ast::Type; use solang_parser::pt::Loc; /// This function is called whenever an assignment statement of an array is encountered. We have to ensure /// that the variable number of the array is tied to the variable number of the correct temporary variable. /// We have two cases: /// 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) /// 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. /// If that's the case, we return an AllocDynamicArray expression with the size being the temp variable to avoid repetitive expressions in the cfg. pub(crate) fn handle_array_assign( right: Expression, cfg: &mut ControlFlowGraph, vartab: &mut Vartable, pos: &usize, ) -> Expression { if let Expression::AllocDynamicArray(loc, ty @ Type::Array(..), size, option) = right { // If we re-allocate the pointer, create a new temp variable to hold the new array length let temp_res = vartab.temp_name("array_length", &Type::Uint(32)); cfg.add( vartab, Instr::Set { loc: Loc::Codegen, res: temp_res, expr: *size, }, ); cfg.array_lengths_temps.insert(*pos, temp_res); Expression::AllocDynamicArray( loc, ty, Box::new(Expression::Variable(Loc::Codegen, Type::Uint(32), temp_res)), option, ) } else { if let Expression::Variable(_, _, right_res) = &right { // If we have initialized a temp var for this var if cfg.array_lengths_temps.contains_key(right_res) { let to_update = cfg.array_lengths_temps[right_res]; cfg.array_lengths_temps.insert(*pos, to_update); } else { // If the right hand side doesn't have a temp, it must be a function parameter or a struct member. cfg.array_lengths_temps.remove(pos); } } right.clone() } }