-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
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
Proposal: @disableIntrinsics()
builtin function
#22110
Comments
cc @rohlem @Rexicon226 @dweiller @ParfenovIgor since you participated in the discussion on #21833. |
I like the idea, and this mechanism seems like the right tool for the job. The one detail I'm not 100% sure on is the current interplay with inlining (and I think this isn't fully addressed in the langref either):
fn regular_f() void {} //code
noinline fn noinline_f() void {} //code
inline fn inline_f() void {} //code
fn main() { //scope 0
@setRuntimeSafety(x);
@setIntrinsicRecognition(y);
{ //scope 1
// code
}
noinline_f();
inline_f();
regular_f();
} The current example in the langref makes it seem like the settings of scope 0 transitively apply to nested scopes (scope 1 here). What seems unclear to me is whether an I think the simplest (most regular and least surprising) answer would be to reset these scope-local settings for all functions, even for |
Whatever we decide here, it just needs to be consistent among these scoped
I think I'd agree with this. |
Hmm... one important thing to note here is that LLVM only allows This definitely calls into question the value of having |
I definitely agree with having As far as
I think it could be fine to still have it defined at scope-level and let backends that can't support that level of granularity could just hoist |
That's fine by me. We'd need to carefully audit compiler-rt when removing
I can't think of any real-world use cases either. It's probably fine for any |
I changed my mind on scoped vs function-level; it turns out to be much easier to implement at the function level, and also, that's how |
@setIntrinsicRecognition(comptime value: bool)
builtin function@disableIntrinsics()
builtin function
Proposal text updated based on the implementation PR (#22154). |
@disableIntrinsics()
forbids the compiler from recognizing code sequences and turning them into well-known library calls. The obvious examples of this would bememcpy()
,memset()
, etc. Additionally, it forbids the compiler from turning calls to such well-known library functions into different code (e.g. turningmemcpy()
into__aeabi_memcpy()
on Arm).Concretely, for LLVM, this would map to the
no-builtins
function attribute and thenobuiltin
call site attribute, and whatever equivalent exists for other backends.This builtin function would work similarly to
@disableInstrumentation()
in that a call to it affects the entire function body rather than the block scope. The existing-fno-builtin
compiler option works as if@disableIntrinsics()
is called in every function.Consider one motivating use case from the standard library:
zig/lib/std/start.zig
Lines 450 to 488 in aa7d138
zig/lib/std/os/linux/pie.zig
Lines 202 to 304 in aa7d138
All of the code that runs prior to applying relocations in
std.os.linux.pie.relocate()
is potentially vulnerable to an optimization pass or compiler backend deciding to turn some code sequence into a library call, and we have to massage it just right to prevent that from happening. This is obviously quite fragile. Other kinds of software like libcs, dynamic linkers, kernels, kernel modules, etc face similar problems and consequently make use of-fno-builtin
or Clang'sno_builtin
attribute.Another motivating use case can be found here: #21831 (comment)
Yet more use cases would be
memcpy()
,memset()
, etc implementations in compiler-rt.I don't think
-fno-builtin
is an appropriate substitute for a language feature here; in the case above, we can't apply-fno-builtin
to just that code, but we obviously don't want to apply-fno-builtin
to the entire standard library either. That said, I don't think we need the level of granularity that Clang'sno_builtin
attribute has; I think a builtin function in the form proposed here strikes a good balance.This proposal is related to #21833. That proposal is about preventing the compiler from turning a single call to a well-known library function into something else (e.g.
__aeabi_memcpy()
on Arm). This proposal encompasses that behavior, but only for an entire function body rather than individual calls. I suspect this will be good enough in practice, so this proposal could be considered to supersede #21833 (although technically there's no particular reason that they can't both be implemented).The text was updated successfully, but these errors were encountered: