mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-29 20:46:07 +03:00
e7b84604cb
These types are Id's to a table stored in TLS, so using them from another tread will either panic, or give wrong results. Therefor, I've added a `ThreadLocalIndex` marker type, which ensures types arn't `Send`/`Sync`. This is a breaking change for users of the `rustc_public` crate. Zulip Discussion: https://rust-lang.zulipchat.com/#narrow/channel/320896-project-stable-mir/topic/WDYM.20.22should.20not.20.20be.20shared.20across.20threads.22/with/547374171
83 lines
3.0 KiB
Rust
83 lines
3.0 KiB
Rust
//! This module provides methods to retrieve allocation information, such as static variables.
|
|
|
|
use std::io::Read;
|
|
|
|
use serde::Serialize;
|
|
|
|
use crate::mir::mono::{Instance, StaticDef};
|
|
use crate::target::{Endian, MachineInfo};
|
|
use crate::ty::{Allocation, Binder, ExistentialTraitRef, Ty, index_impl};
|
|
use crate::{Error, ThreadLocalIndex, with};
|
|
|
|
/// An allocation in the rustc_public's IR global memory can be either a function pointer,
|
|
/// a static, or a "real" allocation with some data in it.
|
|
#[derive(Debug, Clone, Eq, PartialEq, Serialize)]
|
|
pub enum GlobalAlloc {
|
|
/// The alloc ID is used as a function pointer.
|
|
Function(Instance),
|
|
/// This alloc ID points to a symbolic (not-reified) vtable.
|
|
/// The `None` trait ref is used to represent auto traits.
|
|
VTable(Ty, Option<Binder<ExistentialTraitRef>>),
|
|
/// The alloc ID points to a "lazy" static variable that did not get computed (yet).
|
|
/// This is also used to break the cycle in recursive statics.
|
|
Static(StaticDef),
|
|
/// The alloc ID points to memory.
|
|
Memory(Allocation),
|
|
/// The first pointer-sized segment of a type id. On 64 bit systems, the 128 bit type id
|
|
/// is split into two segments, on 32 bit systems there are 4 segments, and so on.
|
|
TypeId { ty: Ty },
|
|
}
|
|
|
|
impl From<AllocId> for GlobalAlloc {
|
|
fn from(value: AllocId) -> Self {
|
|
with(|cx| cx.global_alloc(value))
|
|
}
|
|
}
|
|
|
|
impl GlobalAlloc {
|
|
/// Retrieve the allocation id for a global allocation if it exists.
|
|
///
|
|
/// For `[GlobalAlloc::VTable]`, this will return the allocation for the VTable of the given
|
|
/// type for the optional trait if the type implements the trait.
|
|
///
|
|
/// This method will always return `None` for allocations other than `[GlobalAlloc::VTable]`.
|
|
pub fn vtable_allocation(&self) -> Option<AllocId> {
|
|
with(|cx| cx.vtable_allocation(self))
|
|
}
|
|
}
|
|
|
|
/// A unique identification number for each provenance
|
|
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
|
|
pub struct AllocId(usize, ThreadLocalIndex);
|
|
index_impl!(AllocId);
|
|
|
|
/// Utility function used to read an allocation data into a unassigned integer.
|
|
pub(crate) fn read_target_uint(mut bytes: &[u8]) -> Result<u128, Error> {
|
|
let mut buf = [0u8; size_of::<u128>()];
|
|
match MachineInfo::target_endianness() {
|
|
Endian::Little => {
|
|
bytes.read_exact(&mut buf[..bytes.len()])?;
|
|
Ok(u128::from_le_bytes(buf))
|
|
}
|
|
Endian::Big => {
|
|
bytes.read_exact(&mut buf[16 - bytes.len()..])?;
|
|
Ok(u128::from_be_bytes(buf))
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Utility function used to read an allocation data into an assigned integer.
|
|
pub(crate) fn read_target_int(mut bytes: &[u8]) -> Result<i128, Error> {
|
|
let mut buf = [0u8; size_of::<i128>()];
|
|
match MachineInfo::target_endianness() {
|
|
Endian::Little => {
|
|
bytes.read_exact(&mut buf[..bytes.len()])?;
|
|
Ok(i128::from_le_bytes(buf))
|
|
}
|
|
Endian::Big => {
|
|
bytes.read_exact(&mut buf[16 - bytes.len()..])?;
|
|
Ok(i128::from_be_bytes(buf))
|
|
}
|
|
}
|
|
}
|