about summary refs log tree commit diff
path: root/src/librustc
diff options
context:
space:
mode:
authorAndreas Molzer <andreas.molzer@gmx.de>2019-08-30 04:17:18 +0200
committerAndreas Molzer <andreas.molzer@gmx.de>2019-08-30 04:17:18 +0200
commitbee2d3748ef472e416b4a690af89543ed0edd302 (patch)
treea846e4a842df99f7e75019bdcd9c4a3fde1c7950 /src/librustc
parent6fe31fefd80cd1c4300b03b1e55c63de12134eed (diff)
downloadrust-bee2d3748ef472e416b4a690af89543ed0edd302.tar.gz
rust-bee2d3748ef472e416b4a690af89543ed0edd302.zip
Move relocation range copies into allocation
Diffstat (limited to 'src/librustc')
-rw-r--r--src/librustc/mir/interpret/allocation.rs50
1 files changed, 50 insertions, 0 deletions
diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs
index 75319a67831..8f47bf9d0fd 100644
--- a/src/librustc/mir/interpret/allocation.rs
+++ b/src/librustc/mir/interpret/allocation.rs
@@ -693,6 +693,56 @@ impl<Tag> DerefMut for Relocations<Tag> {
     }
 }
 
+/// A partial, owned list of relocations to transfer into another allocation.
+pub struct AllocationRelocations<Tag> {
+    relative_relocations: Vec<(Size, (Tag, AllocId))>,
+}
+
+impl<Tag: Copy, Extra> Allocation<Tag, Extra> {
+    pub fn prepare_relocation_copy(
+        &self,
+        cx: &impl HasDataLayout,
+        src: Pointer<Tag>,
+        size: Size,
+        dest: Pointer<Tag>,
+        length: u64,
+    ) -> AllocationRelocations<Tag> {
+        let relocations = self.get_relocations(cx, src, size);
+        if relocations.is_empty() {
+            return AllocationRelocations { relative_relocations: Vec::new() };
+        }
+
+        let mut new_relocations = Vec::with_capacity(relocations.len() * (length as usize));
+
+        for i in 0..length {
+            new_relocations.extend(
+                relocations
+                .iter()
+                .map(|&(offset, reloc)| {
+                    // compute offset for current repetition
+                    let dest_offset = dest.offset + (i * size);
+                    (
+                        // shift offsets from source allocation to destination allocation
+                        offset + dest_offset - src.offset,
+                        reloc,
+                        )
+                })
+                );
+        }
+
+        AllocationRelocations {
+            relative_relocations: new_relocations,
+        }
+    }
+
+    pub fn mark_relocation_range(
+        &mut self,
+        relocations: AllocationRelocations<Tag>,
+    ) {
+        self.relocations.insert_presorted(relocations.relative_relocations);
+    }
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // Undefined byte tracking
 ////////////////////////////////////////////////////////////////////////////////