Implement #[ffi_const]
and #[ffi_pure]
function attributes
Introduce function attribute corresponding to the `const`/`pure` attributes supported by GCC, clang and other compilers. Based on the work of gnzlbg <gonzalobg88@gmail.com>.
This commit is contained in:
parent
3a7dfda40a
commit
abc236414b
@ -284,6 +284,12 @@ pub fn from_fn_attrs(cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, instance: ty::
|
||||
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::FFI_RETURNS_TWICE) {
|
||||
Attribute::ReturnsTwice.apply_llfn(Function, llfn);
|
||||
}
|
||||
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::FFI_PURE) {
|
||||
Attribute::ReadOnly.apply_llfn(Function, llfn);
|
||||
}
|
||||
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::FFI_CONST) {
|
||||
Attribute::ReadNone.apply_llfn(Function, llfn);
|
||||
}
|
||||
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
|
||||
naked(llfn, true);
|
||||
}
|
||||
|
@ -616,4 +616,7 @@
|
||||
E0724, // `#[ffi_returns_twice]` is only allowed in foreign functions
|
||||
E0726, // non-explicit (not `'_`) elided lifetime in unsupported position
|
||||
// E0738, // Removed; errored on `#[track_caller] fn`s in `extern "Rust" { ... }`.
|
||||
E0755, // `#[ffi_pure]` is only allowed on foreign functions
|
||||
E0756, // `#[ffi_const]` is only allowed on foreign functions
|
||||
E0757, // `#[ffi_const]` functions cannot be `#[ffi_pure]`
|
||||
}
|
||||
|
@ -565,6 +565,12 @@ pub fn set(&self, features: &mut Features, span: Span) {
|
||||
/// Allow conditional compilation depending on rust version
|
||||
(active, cfg_version, "1.45.0", Some(64796), None),
|
||||
|
||||
/// Allows the use of `#[ffi_pure]` on foreign functions.
|
||||
(active, ffi_pure, "1.45.0", Some(58329), None),
|
||||
|
||||
/// Allows the use of `#[ffi_const]` on foreign functions.
|
||||
(active, ffi_const, "1.45.0", Some(58328), None),
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// feature-group-end: actual feature gates
|
||||
// -------------------------------------------------------------------------
|
||||
|
@ -331,6 +331,8 @@ macro_rules! experimental {
|
||||
),
|
||||
|
||||
gated!(ffi_returns_twice, Whitelisted, template!(Word), experimental!(ffi_returns_twice)),
|
||||
gated!(ffi_pure, Whitelisted, template!(Word), experimental!(ffi_pure)),
|
||||
gated!(ffi_const, Whitelisted, template!(Word), experimental!(ffi_const)),
|
||||
gated!(track_caller, Whitelisted, template!(Word), experimental!(track_caller)),
|
||||
gated!(
|
||||
register_attr, CrateLevel, template!(List: "attr1, attr2, ..."),
|
||||
|
@ -77,6 +77,12 @@ pub struct CodegenFnAttrFlags: u32 {
|
||||
const NO_SANITIZE_THREAD = 1 << 14;
|
||||
/// All `#[no_sanitize(...)]` attributes.
|
||||
const NO_SANITIZE_ANY = Self::NO_SANITIZE_ADDRESS.bits | Self::NO_SANITIZE_MEMORY.bits | Self::NO_SANITIZE_THREAD.bits;
|
||||
/// #[ffi_pure]: applies clang's `pure` attribute to a foreign function
|
||||
/// declaration.
|
||||
const FFI_PURE = 1 << 15;
|
||||
/// #[ffi_const]: applies clang's `const` attribute to a foreign function
|
||||
/// declaration.
|
||||
const FFI_CONST = 1 << 16;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -322,6 +322,8 @@
|
||||
f32,
|
||||
f64,
|
||||
feature,
|
||||
ffi_const,
|
||||
ffi_pure,
|
||||
ffi_returns_twice,
|
||||
field,
|
||||
field_init_shorthand,
|
||||
|
@ -2374,6 +2374,43 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
} else if attr.check_name(sym::ffi_pure) {
|
||||
if tcx.is_foreign_item(id) {
|
||||
if attrs.iter().any(|a| a.check_name(sym::ffi_const)) {
|
||||
// `#[ffi_const]` functions cannot be `#[ffi_pure]`
|
||||
struct_span_err!(
|
||||
tcx.sess,
|
||||
attr.span,
|
||||
E0757,
|
||||
"`#[ffi_const]` function cannot be `#[ffi_pure]`"
|
||||
)
|
||||
.emit();
|
||||
} else {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_PURE;
|
||||
}
|
||||
} else {
|
||||
// `#[ffi_pure]` is only allowed on foreign functions
|
||||
struct_span_err!(
|
||||
tcx.sess,
|
||||
attr.span,
|
||||
E0755,
|
||||
"`#[ffi_pure]` may only be used on foreign functions"
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
} else if attr.check_name(sym::ffi_const) {
|
||||
if tcx.is_foreign_item(id) {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_CONST;
|
||||
} else {
|
||||
// `#[ffi_const]` is only allowed on foreign functions
|
||||
struct_span_err!(
|
||||
tcx.sess,
|
||||
attr.span,
|
||||
E0756,
|
||||
"`#[ffi_const]` may only be used on foreign functions"
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
} else if attr.check_name(sym::rustc_allocator_nounwind) {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_ALLOCATOR_NOUNWIND;
|
||||
} else if attr.check_name(sym::naked) {
|
||||
|
Loading…
Reference in New Issue
Block a user