| 166 | } |
| 167 | |
| 168 | fn diff_instructions( |
| 169 | left_insts: &[InstructionRef], |
| 170 | right_insts: &[InstructionRef], |
| 171 | ) -> Result<(Vec<InstructionDiffRow>, Vec<InstructionDiffRow>)> { |
| 172 | let left_ops = left_insts.iter().map(|i| i.opcode).collect::<Vec<_>>(); |
| 173 | let right_ops = right_insts.iter().map(|i| i.opcode).collect::<Vec<_>>(); |
| 174 | let ops = similar::capture_diff_slices(similar::Algorithm::Patience, &left_ops, &right_ops); |
| 175 | if ops.is_empty() { |
| 176 | ensure!(left_insts.len() == right_insts.len()); |
| 177 | let left_diff = left_insts |
| 178 | .iter() |
| 179 | .map(|i| InstructionDiffRow { ins_ref: Some(*i), ..Default::default() }) |
| 180 | .collect(); |
| 181 | let right_diff = right_insts |
| 182 | .iter() |
| 183 | .map(|i| InstructionDiffRow { ins_ref: Some(*i), ..Default::default() }) |
| 184 | .collect(); |
| 185 | return Ok((left_diff, right_diff)); |
| 186 | } |
| 187 | |
| 188 | let row_count = ops |
| 189 | .iter() |
| 190 | .map(|op| match *op { |
| 191 | similar::DiffOp::Equal { len, .. } => len, |
| 192 | similar::DiffOp::Delete { old_len, .. } => old_len, |
| 193 | similar::DiffOp::Insert { new_len, .. } => new_len, |
| 194 | similar::DiffOp::Replace { old_len, new_len, .. } => old_len.max(new_len), |
| 195 | }) |
| 196 | .sum(); |
| 197 | let mut left_diff = Vec::<InstructionDiffRow>::with_capacity(row_count); |
| 198 | let mut right_diff = Vec::<InstructionDiffRow>::with_capacity(row_count); |
| 199 | for op in ops { |
| 200 | let (_tag, left_range, right_range) = op.as_tag_tuple(); |
| 201 | let len = left_range.len().max(right_range.len()); |
| 202 | left_diff.extend( |
| 203 | left_range |
| 204 | .clone() |
| 205 | .map(|i| InstructionDiffRow { ins_ref: Some(left_insts[i]), ..Default::default() }), |
| 206 | ); |
| 207 | right_diff.extend( |
| 208 | right_range.clone().map(|i| InstructionDiffRow { |
| 209 | ins_ref: Some(right_insts[i]), |
| 210 | ..Default::default() |
| 211 | }), |
| 212 | ); |
| 213 | if left_range.len() < len { |
| 214 | left_diff.extend((left_range.len()..len).map(|_| InstructionDiffRow::default())); |
| 215 | } |
| 216 | if right_range.len() < len { |
| 217 | right_diff.extend((right_range.len()..len).map(|_| InstructionDiffRow::default())); |
| 218 | } |
| 219 | } |
| 220 | Ok((left_diff, right_diff)) |
| 221 | } |
| 222 | |
| 223 | fn arg_to_string(arg: &InstructionArg, reloc: Option<ResolvedRelocation>) -> String { |
| 224 | match arg { |