-
Notifications
You must be signed in to change notification settings - Fork 12.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Allocation to SMIR #114466
Add Allocation to SMIR #114466
Conversation
This PR changes Stable MIR cc @oli-obk, @celinval, @spastorino Some changes occurred to the CTFE / Miri engine cc @rust-lang/miri |
pub fn bytes(&self) -> &Option<Box<SortedMap<Size, Prov>>> { | ||
&self.bytes | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we can ignore this, this will always be empty except for miri
@@ -185,7 +193,7 @@ impl InitMask { | |||
// Note: for performance reasons when interning, some of the fields can be partially | |||
// hashed. (see the `Hash` impl below for more details), so the impl is not derived. | |||
#[derive(Clone, Debug, Eq, PartialEq, HashStable)] | |||
struct InitMaskMaterialized { | |||
pub struct InitMaskMaterialized { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
keep this private. Instead add an iterator over u64
that allows getting the blocks out directly (and just produces the same value over and over in case it was lazy). If you need to box those iterators, that's fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can just store a Vec<u64>
in SMIR, we don't need to use this optimization for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
keep this private.
if I make it private I would have to remove Stable
implementation for it. Can't implement trait for private type. (can I?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can't, but you can add a function returning the iterator I described to InitMask
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
keep this private. Instead add an iterator over
u64
that allows getting the blocks out directly (and just produces the same value over and over in case it was lazy). If you need to box those iterators, that's fine.
but don't we lose information if it's InitMaskBlocks::Lazy{true}
or InitMaskBlocks::Lazy(false)
, how would someone know if it's lazy or not, since I can't match private value. Maybe something like this ? So people who use smir could identify it it's by checking repeating 0's or 1's
vec![1;10].iter() // lazy ?
vec![0;10].iter() // not lazy ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lazy is not information anyone cares about. It is just an internal representation detail. it's a optimization to avoid allocating a vec if all entries are true or all entries are false
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah I get it now, I didn't know it wasn't useful for smir
mod init_mask; | ||
mod provenance_map; | ||
pub mod init_mask; | ||
pub mod provenance_map; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was all quite deliberately sealed away. Do we really have to make this public? :(
Not even the interpreter or codegen need that kind of access. I don't think anything can legitimately require it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're gonna make it private before this PR lands. We're not exposing the internals, but adding helper methods that avoid having to expose them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't need to add any helper methods. The existing methods are sufficient for the interpreter, codegen, and MiniRust.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but these do random access, we want to duplicate the information. Iterating over all bytes is... not great.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No they don't. They build a full model of the allocation contents in MiniRust / LLVM. I really can't see how you would need more APIs than what is required to build a fully accurate model of Rust semantics aka MiniRust.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yea, I assumed that was too expensive for big allocations, but we can optimize when we see that being an issue
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Made them private, I think in future PR we should def get inspiration from MiniRust.
|
||
pub type Bytes = Vec<u8>; | ||
pub type Size = usize; | ||
pub type Prov = usize; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be AllocId
. How is that exposed to smir?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar to how we have a table for DefId
s, we should add something like it for AllocId
s (instead of exposing the AllocId
s internals). Since we don't actually need this in this PR yet, we can make Prov
just be Opaque
and stick a stringified version of the AllocId
in it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I made it Opaque
#[derive(Clone, Debug)] | ||
pub struct ProvenanceMap { | ||
pub ptrs: Vec<(Size, Prov)>, | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will not be very useful without doc comments explaining what this is all about.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added comments from rustc, I don't know specifics of what smir user would want to know from this. I think it should suffice for now? If not I would love to learn more and add more information/documentation.
@@ -64,6 +64,13 @@ impl InitMask { | |||
} | |||
} | |||
|
|||
pub fn get_blocks(&self) -> Box<std::slice::Iter<'_, u64>> { | |||
match &self.blocks { | |||
InitMaskBlocks::Lazy { state: _ } => Box::new([].iter()), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is wrong, it's not zero sized, but repeating state
for the length of the entire bytes
buffer.
But, as Ralf mentioned, we can avoid this entirely by encoding bytes
as Vec<Option<u8>>
and using https://github.com/RalfJung/minirust/blob/196da9640a4cd608405ad40110d29930827a99a5/tooling/minimize/src/constant.rs#L132-L145 to generate that Vec
. Then we don't need an init_mask
field at all.
provenance: { | ||
let mut ptrs = Vec::new(); | ||
for (size, prov) in self.provenance().ptrs().iter() { | ||
ptrs.push((size.bytes_usize(), opaque(&prov.0.get()))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ptrs.push((size.bytes_usize(), opaque(&prov.0.get()))); | |
ptrs.push((size.bytes_usize(), opaque(prov))); |
when we render it opaquely, just render the full thing instead of its internal information
let mut blocks = Vec::new(); | ||
for i in self.init_mask().get_blocks() { | ||
blocks.push(*i); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This and get_blocks
is now dead code
#[derive(Clone, Debug)] | ||
pub enum InitMaskBlocks { | ||
Materialized(InitMaskMaterialized), | ||
} | ||
|
||
#[derive(Clone, Debug)] | ||
pub struct InitMask { | ||
pub blocks: InitMaskBlocks, | ||
pub len: Size, | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
THis isn't needed anymore either
Please squash the commits after all comments have been addressed |
c2c3c54
to
fc63e74
Compare
use super::{ | ||
read_target_uint, write_target_uint, AllocId, InterpError, InterpResult, Pointer, Provenance, | ||
ResourceExhaustionInfo, Scalar, ScalarSizeMismatch, UndefinedBehaviorInfo, UninitBytesAccess, | ||
UnsupportedOpInfo, | ||
}; | ||
use crate::ty; | ||
use init_mask::*; | ||
use provenance_map::*; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like some spurious remainders, these are now just unnecessary changes.
@bors r+ rollup |
Add Allocation to SMIR As it's discussed [here ](https://rust-lang.zulipchat.com/#narrow/stream/320896-project-stable-mir/topic/Representing.20Constants.20in.20smir)this is an attempt to cover Constants for smir in a different way compared to rust-lang#114342 cc rust-lang/project-stable-mir#15 r? `@oli-obk`
…iaskrgr Rollup of 5 pull requests Successful merges: - rust-lang#114466 (Add Allocation to SMIR) - rust-lang#114505 (Add documentation to has_deref) - rust-lang#114519 (use offset_of! to calculate dirent64 field offsets) - rust-lang#114537 (Migrate GUI colors test to original CSS color format) - rust-lang#114539 (linkchecker: Remove unneeded FIXME about intra-doc links) Failed merges: - rust-lang#114485 (Add trait decls to SMIR) r? `@ghost` `@rustbot` modify labels: rollup
Convert Const to Allocation in smir Continuation of previous pr rust-lang#114466 cc rust-lang/project-stable-mir#15 r? `@oli-obk`
Convert Const to Allocation in smir Continuation of previous pr rust-lang/rust#114466 cc rust-lang/project-stable-mir#15 r? `@oli-obk`
Convert Const to Allocation in smir Continuation of previous pr rust-lang/rust#114466 cc rust-lang/project-stable-mir#15 r? `@oli-obk`
As it's discussed here this is an attempt to cover Constants for smir in a different way compared to #114342
cc rust-lang/project-stable-mir#15
r? @oli-obk