Copy and translate global values from the callee into the caller.
(func: &mut ir::Function, callee: &ir::Function)
| 1426 | |
| 1427 | /// Copy and translate global values from the callee into the caller. |
| 1428 | fn create_global_values(func: &mut ir::Function, callee: &ir::Function) -> CodegenResult<u32> { |
| 1429 | let gv_offset = func.global_values.len(); |
| 1430 | let gv_offset = u32::try_from(gv_offset).unwrap(); |
| 1431 | |
| 1432 | func.global_values.reserve(callee.global_values.len()); |
| 1433 | for gv in callee.global_values.values() { |
| 1434 | // Re-insert callee mem flags into the caller's DFG before constructing |
| 1435 | // the global value data, to avoid borrow conflicts. |
| 1436 | let remapped_flags = match gv { |
| 1437 | ir::GlobalValueData::Load { flags, .. } => { |
| 1438 | let mut flags_data = callee.dfg.mem_flags[*flags]; |
| 1439 | // Remap alias region entity from callee to caller. |
| 1440 | if let Some(callee_region) = flags_data.alias_region() { |
| 1441 | let region_data = callee.dfg.alias_regions[callee_region].clone(); |
| 1442 | let caller_region = func.dfg.alias_regions.insert(region_data); |
| 1443 | flags_data.set_alias_region(Some(caller_region)); |
| 1444 | } |
| 1445 | Some( |
| 1446 | func.dfg |
| 1447 | .mem_flags |
| 1448 | .insert(flags_data) |
| 1449 | .map_err(|_| crate::result::CodegenError::ImplLimitExceeded)?, |
| 1450 | ) |
| 1451 | } |
| 1452 | _ => None, |
| 1453 | }; |
| 1454 | func.global_values.push(match gv { |
| 1455 | // These kinds of global values reference other global values, so we |
| 1456 | // need to fixup that reference. |
| 1457 | ir::GlobalValueData::Load { |
| 1458 | base, |
| 1459 | offset, |
| 1460 | global_type, |
| 1461 | flags: _, |
| 1462 | } => ir::GlobalValueData::Load { |
| 1463 | base: ir::GlobalValue::from_u32(base.as_u32() + gv_offset), |
| 1464 | offset: *offset, |
| 1465 | global_type: *global_type, |
| 1466 | flags: remapped_flags.unwrap(), |
| 1467 | }, |
| 1468 | ir::GlobalValueData::IAddImm { |
| 1469 | base, |
| 1470 | offset, |
| 1471 | global_type, |
| 1472 | } => ir::GlobalValueData::IAddImm { |
| 1473 | base: ir::GlobalValue::from_u32(base.as_u32() + gv_offset), |
| 1474 | offset: *offset, |
| 1475 | global_type: *global_type, |
| 1476 | }, |
| 1477 | |
| 1478 | // These kinds of global values do not reference other global |
| 1479 | // values, so we can just clone them. |
| 1480 | ir::GlobalValueData::VMContext |
| 1481 | | ir::GlobalValueData::Symbol { .. } |
| 1482 | | ir::GlobalValueData::DynScaleTargetConst { .. } => gv.clone(), |
| 1483 | }); |
| 1484 | } |
| 1485 |
no test coverage detected