note on integer-pointer transmutation
[web.git] / personal / _posts / 2022-04-11-provenance-exposed.md
index 24b340236a37cf1e29d0c1e3d8dfc92075fbb6e2..53d0b84f044db8c0a79d69cb9e2204b76725c778 100644 (file)
@@ -261,7 +261,7 @@ So what are the alternatives?
 Well, I would argue that the alternative is to treat the original program (after translation to Rust) as having Undefined Behavior.
 There are, to my knowledge, generally two reasons why people might want to transmute a pointer to an integer:
 - Chaining many `as` casts is annoying, so calling `mem::transmute` might be shorter.
 Well, I would argue that the alternative is to treat the original program (after translation to Rust) as having Undefined Behavior.
 There are, to my knowledge, generally two reasons why people might want to transmute a pointer to an integer:
 - Chaining many `as` casts is annoying, so calling `mem::transmute` might be shorter.
-- The code doesn't actually care about the *integer* per se, it just needs *some way* to hold arbitrary data in a container of a given time.
+- The code doesn't actually care about the *integer* per se, it just needs *some way* to hold arbitrary data in a container of a given type.
 
 The first kind of code should just use `as` casts, and we should do what we can (via lints, for example) to identify such code and get it to use casts instead.[^compat]
 Maybe we can adjust the cast rules to remove the need for chaining, or add some [helper methods](https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.expose_addr) that can be used instead.
 
 The first kind of code should just use `as` casts, and we should do what we can (via lints, for example) to identify such code and get it to use casts instead.[^compat]
 Maybe we can adjust the cast rules to remove the need for chaining, or add some [helper methods](https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.expose_addr) that can be used instead.
@@ -328,7 +328,7 @@ Compositionality at its finest!
 
 I have talked a lot about my vision for "solving" pointer provenance in Rust.
 What about other languages?
 
 I have talked a lot about my vision for "solving" pointer provenance in Rust.
 What about other languages?
-As you might have heard, C is moving towards making [PNVI-ae-udi](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2577.pdf) an official recommendation for how to interpret the C memory model.
+As you might have heard, C is moving towards making [PNVI-ae-udi](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2676.pdf) an official recommendation for how to interpret the C memory model.
 With C having so much more legacy code to care about and many more stakeholders than Rust does, this is an impressive achievement!
 How does it compare to all I said above?
 
 With C having so much more legacy code to care about and many more stakeholders than Rust does, this is an impressive achievement!
 How does it compare to all I said above?
 
@@ -421,13 +421,17 @@ My personal stance is that we should not let the cast synthesize a new provenanc
 This would entirely lose the benefit I discussed above of making pointer-integer round-trips a *local* concern -- if these round-trips produce new, never-before-seen kinds of provenance, then the entire rest of the memory model has to define how it deals with those provenances.
 We already have no choice but treat pointer-integer casts as an operation with side-effects; let's just do the same with integer-pointer casts and remain sure that no matter what the aliasing rules are, they will work fine even in the presence of pointer-integer round-trips.
 
 This would entirely lose the benefit I discussed above of making pointer-integer round-trips a *local* concern -- if these round-trips produce new, never-before-seen kinds of provenance, then the entire rest of the memory model has to define how it deals with those provenances.
 We already have no choice but treat pointer-integer casts as an operation with side-effects; let's just do the same with integer-pointer casts and remain sure that no matter what the aliasing rules are, they will work fine even in the presence of pointer-integer round-trips.
 
+That said, under this model integer-pointer casts still have no side-effect, in the sense that just removing them (if their result is unused) is fine.
+Hence, it *could* make sense to implicitly perform integer-pointer casts in some situations, like when an integer value (without provenance) is used in a pointer operation (due to an integer-to-pointer transmutation).
+This breaks some optimizations like load fusion (turning two loads into one assumes the same provenance was picked both times), but most optimizations (in particular dead code elimination) are unaffected.
+
 #### What about LLVM?
 
 I discussed above how my vision for Rust relates to the direction C is moving towards.
 What does that mean for the design space of LLVM?
 #### What about LLVM?
 
 I discussed above how my vision for Rust relates to the direction C is moving towards.
 What does that mean for the design space of LLVM?
-Which changes need to be made to fix (potential) miscompilations in LLVM and to make it compatible with these ideas for C and/or Rust?
+Which changes would have to be made to fix (potential) miscompilations in LLVM and to make it compatible with these ideas for C and/or Rust?
 Here's the list of open problems I am aware of:
 Here's the list of open problems I am aware of:
-- LLVM needs to stop [removing `inttoptr(ptrtoint(_))`](https://github.com/llvm/llvm-project/issues/33896) and stop doing [replacement of `==`-equal pointers](https://github.com/llvm/llvm-project/issues/34577).
+- LLVM would have to to stop [removing `inttoptr(ptrtoint(_))`](https://github.com/llvm/llvm-project/issues/33896) and stop doing [replacement of `==`-equal pointers](https://github.com/llvm/llvm-project/issues/34577).
 - As the first example shows, LLVM also needs to treat `ptrtoint` as a side-effecting operation that has to be kept around even when its result is unused. (Of course, as with everything I say here, there can be special cases where the old optimizations are still correct, but they need extra justification.)
 - I think LLVM should also treat `inttoptr` as a side-effecting (and, in particular, non-deterministic) operation, as per the last example. However, this could possibly be avoided with a `noalias` model that specifically accounts for new kinds of provenance being synthesized by casts. (I am being vague here since I don't know what that provenance needs to look like.)
 
 - As the first example shows, LLVM also needs to treat `ptrtoint` as a side-effecting operation that has to be kept around even when its result is unused. (Of course, as with everything I say here, there can be special cases where the old optimizations are still correct, but they need extra justification.)
 - I think LLVM should also treat `inttoptr` as a side-effecting (and, in particular, non-deterministic) operation, as per the last example. However, this could possibly be avoided with a `noalias` model that specifically accounts for new kinds of provenance being synthesized by casts. (I am being vague here since I don't know what that provenance needs to look like.)