Skip to content

Commit abc2364

Browse files
committed
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 <[email protected]>.
1 parent 3a7dfda commit abc2364

File tree

7 files changed

+62
-0
lines changed

7 files changed

+62
-0
lines changed

src/librustc_codegen_llvm/attributes.rs

+6
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,12 @@ pub fn from_fn_attrs(cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, instance: ty::
284284
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::FFI_RETURNS_TWICE) {
285285
Attribute::ReturnsTwice.apply_llfn(Function, llfn);
286286
}
287+
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::FFI_PURE) {
288+
Attribute::ReadOnly.apply_llfn(Function, llfn);
289+
}
290+
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::FFI_CONST) {
291+
Attribute::ReadNone.apply_llfn(Function, llfn);
292+
}
287293
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
288294
naked(llfn, true);
289295
}

src/librustc_error_codes/error_codes.rs

+3
Original file line numberDiff line numberDiff line change
@@ -616,4 +616,7 @@ E0754: include_str!("./error_codes/E0754.md"),
616616
E0724, // `#[ffi_returns_twice]` is only allowed in foreign functions
617617
E0726, // non-explicit (not `'_`) elided lifetime in unsupported position
618618
// E0738, // Removed; errored on `#[track_caller] fn`s in `extern "Rust" { ... }`.
619+
E0755, // `#[ffi_pure]` is only allowed on foreign functions
620+
E0756, // `#[ffi_const]` is only allowed on foreign functions
621+
E0757, // `#[ffi_const]` functions cannot be `#[ffi_pure]`
619622
}

src/librustc_feature/active.rs

+6
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,12 @@ declare_features! (
565565
/// Allow conditional compilation depending on rust version
566566
(active, cfg_version, "1.45.0", Some(64796), None),
567567

568+
/// Allows the use of `#[ffi_pure]` on foreign functions.
569+
(active, ffi_pure, "1.45.0", Some(58329), None),
570+
571+
/// Allows the use of `#[ffi_const]` on foreign functions.
572+
(active, ffi_const, "1.45.0", Some(58328), None),
573+
568574
// -------------------------------------------------------------------------
569575
// feature-group-end: actual feature gates
570576
// -------------------------------------------------------------------------

src/librustc_feature/builtin_attrs.rs

+2
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,8 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
331331
),
332332

333333
gated!(ffi_returns_twice, Whitelisted, template!(Word), experimental!(ffi_returns_twice)),
334+
gated!(ffi_pure, Whitelisted, template!(Word), experimental!(ffi_pure)),
335+
gated!(ffi_const, Whitelisted, template!(Word), experimental!(ffi_const)),
334336
gated!(track_caller, Whitelisted, template!(Word), experimental!(track_caller)),
335337
gated!(
336338
register_attr, CrateLevel, template!(List: "attr1, attr2, ..."),

src/librustc_middle/middle/codegen_fn_attrs.rs

+6
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,12 @@ bitflags! {
7777
const NO_SANITIZE_THREAD = 1 << 14;
7878
/// All `#[no_sanitize(...)]` attributes.
7979
const NO_SANITIZE_ANY = Self::NO_SANITIZE_ADDRESS.bits | Self::NO_SANITIZE_MEMORY.bits | Self::NO_SANITIZE_THREAD.bits;
80+
/// #[ffi_pure]: applies clang's `pure` attribute to a foreign function
81+
/// declaration.
82+
const FFI_PURE = 1 << 15;
83+
/// #[ffi_const]: applies clang's `const` attribute to a foreign function
84+
/// declaration.
85+
const FFI_CONST = 1 << 16;
8086
}
8187
}
8288

src/librustc_span/symbol.rs

+2
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,8 @@ symbols! {
322322
f32,
323323
f64,
324324
feature,
325+
ffi_const,
326+
ffi_pure,
325327
ffi_returns_twice,
326328
field,
327329
field_init_shorthand,

src/librustc_typeck/collect.rs

+37
Original file line numberDiff line numberDiff line change
@@ -2374,6 +2374,43 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
23742374
)
23752375
.emit();
23762376
}
2377+
} else if attr.check_name(sym::ffi_pure) {
2378+
if tcx.is_foreign_item(id) {
2379+
if attrs.iter().any(|a| a.check_name(sym::ffi_const)) {
2380+
// `#[ffi_const]` functions cannot be `#[ffi_pure]`
2381+
struct_span_err!(
2382+
tcx.sess,
2383+
attr.span,
2384+
E0757,
2385+
"`#[ffi_const]` function cannot be `#[ffi_pure]`"
2386+
)
2387+
.emit();
2388+
} else {
2389+
codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_PURE;
2390+
}
2391+
} else {
2392+
// `#[ffi_pure]` is only allowed on foreign functions
2393+
struct_span_err!(
2394+
tcx.sess,
2395+
attr.span,
2396+
E0755,
2397+
"`#[ffi_pure]` may only be used on foreign functions"
2398+
)
2399+
.emit();
2400+
}
2401+
} else if attr.check_name(sym::ffi_const) {
2402+
if tcx.is_foreign_item(id) {
2403+
codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_CONST;
2404+
} else {
2405+
// `#[ffi_const]` is only allowed on foreign functions
2406+
struct_span_err!(
2407+
tcx.sess,
2408+
attr.span,
2409+
E0756,
2410+
"`#[ffi_const]` may only be used on foreign functions"
2411+
)
2412+
.emit();
2413+
}
23772414
} else if attr.check_name(sym::rustc_allocator_nounwind) {
23782415
codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_ALLOCATOR_NOUNWIND;
23792416
} else if attr.check_name(sym::naked) {

0 commit comments

Comments
 (0)