-
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
Wishlist: allow adding intrinsics in a way that doesn't break every backend #93145
Comments
Oh I should've written this up long ago... basically the plan @eddyb and I had for this was to add an attribute (like lang item, but intrinsic) that can be added to functions and methods. It would essentially work like your proposal, but you could annotate the methods on the integer types directly instead of having to redeclare an intrinsic for them. |
#96946 is a nice example where this would have been really handy -- |
Add a query for checking whether a function is an intrinsic. work towards rust-lang#93145 This will reduce churn when we add more ways to declare intrinsics r? `@scottmcm`
Add a query for checking whether a function is an intrinsic. work towards rust-lang#93145 This will reduce churn when we add more ways to declare intrinsics r? `@scottmcm`
Another thought here: since GCC Rust is trying to use an unmodified |
So, I was thinking about working on this ever since @scottmcm mentioned it in #96946. Today I've finally started looking into it...
If someone would be able to mentor me that would be very nice 🥲 |
I think we'll want to avoid the We can keep the existing logic around, but it should mostly not matter, as |
Implement intrinsics with fallback bodies fixes rust-lang#93145 (though we can port many more intrinsics) cc rust-lang#63585 The way this works is that the backend logic for generating custom code for intrinsics has been made fallible. The only failure path is "this intrinsic is unknown". The `Instance` (that was `InstanceDef::Intrinsic`) then gets converted to `InstanceDef::Item`, which represents the fallback body. A regular function call to that body is then codegenned. This is currently implemented for * codegen_ssa (so llvm and gcc) * codegen_cranelift other backends will need to adjust, but they can just keep doing what they were doing if they prefer (though adding new intrinsics to the compiler will then require them to implement them, instead of getting the fallback body). cc `@scottmcm` `@WaffleLapkin` ### todo * [ ] miri support * [x] default intrinsic name to name of function instead of requiring it to be specified in attribute * [x] make sure that the bodies are always available (must be collected for metadata)
Implement intrinsics with fallback bodies fixes rust-lang#93145 (though we can port many more intrinsics) cc rust-lang#63585 The way this works is that the backend logic for generating custom code for intrinsics has been made fallible. The only failure path is "this intrinsic is unknown". The `Instance` (that was `InstanceDef::Intrinsic`) then gets converted to `InstanceDef::Item`, which represents the fallback body. A regular function call to that body is then codegenned. This is currently implemented for * codegen_ssa (so llvm and gcc) * codegen_cranelift other backends will need to adjust, but they can just keep doing what they were doing if they prefer (though adding new intrinsics to the compiler will then require them to implement them, instead of getting the fallback body). cc ``@scottmcm`` ``@WaffleLapkin`` ### todo * [ ] miri support * [x] default intrinsic name to name of function instead of requiring it to be specified in attribute * [x] make sure that the bodies are always available (must be collected for metadata)
Implement intrinsics with fallback bodies fixes rust-lang#93145 (though we can port many more intrinsics) cc rust-lang#63585 The way this works is that the backend logic for generating custom code for intrinsics has been made fallible. The only failure path is "this intrinsic is unknown". The `Instance` (that was `InstanceDef::Intrinsic`) then gets converted to `InstanceDef::Item`, which represents the fallback body. A regular function call to that body is then codegenned. This is currently implemented for * codegen_ssa (so llvm and gcc) * codegen_cranelift other backends will need to adjust, but they can just keep doing what they were doing if they prefer (though adding new intrinsics to the compiler will then require them to implement them, instead of getting the fallback body). cc ```@scottmcm``` ```@WaffleLapkin``` ### todo * [ ] miri support * [x] default intrinsic name to name of function instead of requiring it to be specified in attribute * [x] make sure that the bodies are always available (must be collected for metadata)
Implement intrinsics with fallback bodies fixes rust-lang#93145 (though we can port many more intrinsics) cc rust-lang#63585 The way this works is that the backend logic for generating custom code for intrinsics has been made fallible. The only failure path is "this intrinsic is unknown". The `Instance` (that was `InstanceDef::Intrinsic`) then gets converted to `InstanceDef::Item`, which represents the fallback body. A regular function call to that body is then codegenned. This is currently implemented for * codegen_ssa (so llvm and gcc) * codegen_cranelift other backends will need to adjust, but they can just keep doing what they were doing if they prefer (though adding new intrinsics to the compiler will then require them to implement them, instead of getting the fallback body). cc `@scottmcm` `@WaffleLapkin` ### todo * [ ] miri support * [x] default intrinsic name to name of function instead of requiring it to be specified in attribute * [x] make sure that the bodies are always available (must be collected for metadata)
Give some intrinsics fallback bodies cc rust-lang#93145
Rollup merge of rust-lang#121192 - oli-obk:intrinsics2.0, r=WaffleLapkin Give some intrinsics fallback bodies cc rust-lang#93145
Implement intrinsics with fallback bodies fixes rust-lang#93145 (though we can port many more intrinsics) cc rust-lang#63585 The way this works is that the backend logic for generating custom code for intrinsics has been made fallible. The only failure path is "this intrinsic is unknown". The `Instance` (that was `InstanceDef::Intrinsic`) then gets converted to `InstanceDef::Item`, which represents the fallback body. A regular function call to that body is then codegenned. This is currently implemented for * codegen_ssa (so llvm and gcc) * codegen_cranelift other backends will need to adjust, but they can just keep doing what they were doing if they prefer (though adding new intrinsics to the compiler will then require them to implement them, instead of getting the fallback body). cc `@scottmcm` `@WaffleLapkin` ### todo * [ ] miri support * [x] default intrinsic name to name of function instead of requiring it to be specified in attribute * [x] make sure that the bodies are always available (must be collected for metadata)
@oli-obk if I understood this correctly, trying to get the instance body of an intrinsic with fallback body should be OK, is that correct? I was debugging this failure in StableMIR tests, that seemed related to the fact that we are trying to get the body of
|
You can't get the body of an intrinsic instance. You either need to handle the intrinsic instance yourself, or convert it to an item instance with the same def id and args. Then get the body of that |
Would it be OK if StableMIR does that under the hood? If the user requests the body of an intrinsic that has a fallback body, we do the conversion under the hood and return it. |
Yea that seems reasonable. We'll still ICE if the intrinsic does not have a fallback body though. But that's how backends do this, too (or they error out instead of panicking, but it's basically the same thing at this point) |
See previous conversation in https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler/topic/Musing.20on.20intrinsics.20with.20MIR.20available/near/243719813 which was split off from https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler/topic/Considering.20a.20future.20integration.20of.20the.20gcc.20backend/near/243686539
As we get more backends, and as people write more out-of-tree backends, it gets harder and harder to add intrinsics. Right now, you already have to implement every new intrinsic
bootstrap
And that list will just get longer with cg_gcc and whatever.
It would be really nice if there was an easy way to add an intrinsic that only required updating the type/safety checking parts of the compilers, not the backends at all. Then the changes the specific backends to implement the intrinsic in a more efficient way are separable from adding the intrinsic in the first place.
That would probably mean having MIR available for the intrinsic somehow, so the fallback path for intrinsics in backends could be to just use that MIR, rather than failing.
The intrinsics would then only need to be implemented in backends that care. For example,
cg_clif
might not bother overriding some of the unchecked math ones.And it would be really nice for simd, as the fallback implementations would define their semantics in terms of normal scalar rust, which MIRI will always want anyway, and will be very convenient for other platforms or backends that don't have it implemented (yet or ever).
A sketch
This might not be the best way, but for the sake of a starting point, here's a sketch of how maybe it could work.
Back in #61885, which added an
unchecked_sub
intrinsic, I solved step (1) above by addingIt would be nice if, rather than the intrinsic being only declared
it could instead be defined in
core
with the fallback bodyThen the backend could use that MIR, available like the MIR of any generic function (or inline, for non-generics).
The text was updated successfully, but these errors were encountered: