So if you have some MMIO memory, and you make a pointer to the start of it, and then you call
offset, what happens? Specifically, do you get UB from calculating the new address or not?
I guess you shouldn't, because you're in bounds of the MMIO allocation. Whether you actually don't, however, is a different question.
I remember @RalfJ showing me a scary LLVM presentation about how they had to badly special-case pointers originating from integers in order to refrain from mangling them in GEP inbounds and friends... which also mentioned that the special-case code unsurprisingly had bugs.
yeah... good question. very hard to answer. this would be hard to answer even if we had a formal spec of Rust already, and we don't. ;)
but I would say that MMIO memory is "inbounds" for all intents and purposes (you are accessing it, after all). so as long as you make sure that MMIO memory does not overlap with any memory the R-AM knows about, and that you follow
offset's "inbounds" rules using the bound of the MMIO region, you should be good.
by "knows about" I specifically mean "Rust allocations" -- stack and heap and statics
That is also how I feel things should be. Though in practice I am concerned that some parts of LLVM may be tempted to infer from "a GEPi is executed" that "the base pointer is
dereferenceable" which for MMIO of course isn't so great
Oh wait, nevermind, GEPi only returns poison if the inbounds condition is violated, so that would be unsound anyway.
How are you obtaining the pointer to MMIO ?
I expect that API to give you a “fresh” allocation.
For example, mmap gives you a noalias pointer to new virtual memory - independently of whether it is IPC shared or not. From LLVM POV thatsa fresh allocation.
You can use the Alloc size hints to tell LLVM about the size of the allocation at run time
(notice that noalias in return position is different than in argument position)
The pointer is just a usize cast to the right type.
That's fine then.
We assume that you will do pointer arithmetic in bounds of the allocation.
If the assumption is incorrect, your code might get misoptimized, but if the assumption is correct, everything works out - if your code gets misoptimized, Rust or LLVM have a bug.
Or in other words, you only get UB for doing pointer arithmetic that's out-of-bound of the actual allocation.
well you also have to account for the aliasing rules, but since it looks like everything here is raw ptrs those shouldn't come into play