Skip to content

Commit 1dfbb89

Browse files
committed
use Allocation::write_scalar instead of manual endianess logic
1 parent 767d71f commit 1dfbb89

1 file changed

Lines changed: 15 additions & 35 deletions

File tree

compiler/rustc_mir_transform/src/large_enums.rs

Lines changed: 15 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use rustc_abi::{HasDataLayout, Size, TagEncoding, Variants};
2+
use rustc_const_eval::interpret::{Scalar, alloc_range};
23
use rustc_data_structures::fx::FxHashMap;
34
use rustc_middle::mir::interpret::AllocId;
45
use rustc_middle::mir::*;
@@ -23,7 +24,8 @@ use crate::patch::MirPatch;
2324
///
2425
/// In summary, what this does is at runtime determine which enum variant is active,
2526
/// and instead of copying all the bytes of the largest possible variant,
26-
/// copy only the bytes for the currently active variant.
27+
/// copy only the bytes for the currently active variant. The number of bytes to copy is determined
28+
/// by a lookup table: a discriminant-indexed array indicating the size of each variant.
2729
pub(super) struct EnumSizeOpt {
2830
pub(crate) discrepancy: u64,
2931
}
@@ -202,45 +204,23 @@ impl EnumSizeOpt {
202204
return Some((*adt_def, num_discrs, *alloc_id));
203205
}
204206

207+
// Construct an in-memory array mapping discriminant idx to variant size.
205208
let data_layout = tcx.data_layout();
206-
let ptr_sized_int = data_layout.ptr_sized_integer();
207-
let target_bytes = ptr_sized_int.size().bytes() as usize;
208-
let mut data = vec![0; target_bytes * num_discrs];
209-
210-
// We use a macro because `$bytes` can be u32 or u64.
211-
macro_rules! encode_store {
212-
($curr_idx: expr, $endian: expr, $bytes: expr) => {
213-
let bytes = match $endian {
214-
rustc_abi::Endian::Little => $bytes.to_le_bytes(),
215-
rustc_abi::Endian::Big => $bytes.to_be_bytes(),
216-
};
217-
for (i, b) in bytes.into_iter().enumerate() {
218-
data[$curr_idx + i] = b;
219-
}
220-
};
221-
}
222-
223-
for (var_idx, layout) in variants.iter_enumerated() {
224-
let curr_idx =
225-
target_bytes * adt_def.discriminant_for_variant(tcx, var_idx).val as usize;
226-
let sz = layout.size;
227-
match ptr_sized_int {
228-
rustc_abi::Integer::I32 => {
229-
encode_store!(curr_idx, data_layout.endian, sz.bytes() as u32);
230-
}
231-
rustc_abi::Integer::I64 => {
232-
encode_store!(curr_idx, data_layout.endian, sz.bytes());
233-
}
234-
_ => unreachable!(),
235-
};
236-
}
237-
let alloc = interpret::Allocation::from_bytes(
238-
data,
209+
let ptr_size = data_layout.pointer_size();
210+
let mut alloc = interpret::Allocation::from_bytes(
211+
vec![0; ptr_size.bytes_usize() * num_discrs],
239212
tcx.data_layout.ptr_sized_integer().align(&tcx.data_layout).abi,
240-
Mutability::Not,
213+
Mutability::Mut,
241214
(),
242215
);
216+
for (var_idx, layout) in variants.iter_enumerated() {
217+
let curr_idx = ptr_size * adt_def.discriminant_for_variant(tcx, var_idx).val as u64;
218+
let val = Scalar::from_target_usize(layout.size.bytes(), &tcx);
219+
alloc.write_scalar(&tcx, alloc_range(curr_idx, val.size()), val).unwrap();
220+
}
221+
alloc.mutability = Mutability::Not;
243222
let alloc = tcx.reserve_and_set_memory_alloc(tcx.mk_const_alloc(alloc));
223+
244224
Some((*adt_def, num_discrs, *alloc_cache.entry(ty).or_insert(alloc)))
245225
}
246226
}

0 commit comments

Comments
 (0)