Implement ffi_returns_twice attribute
This commit is contained in:
parent
bcfb5e8ac3
commit
c4b46ace55
13 changed files with 79 additions and 0 deletions
|
@ -2518,6 +2518,9 @@ bitflags! {
|
||||||
/// `#[used]`: indicates that LLVM can't eliminate this function (but the
|
/// `#[used]`: indicates that LLVM can't eliminate this function (but the
|
||||||
/// linker can!).
|
/// linker can!).
|
||||||
const USED = 1 << 9;
|
const USED = 1 << 9;
|
||||||
|
/// #[ffi_returns_twice], indicates that an extern function can return
|
||||||
|
/// multiple times
|
||||||
|
const FFI_RETURNS_TWICE = 1 << 10;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -223,6 +223,9 @@ pub fn from_fn_attrs(
|
||||||
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::COLD) {
|
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::COLD) {
|
||||||
Attribute::Cold.apply_llfn(Function, llfn);
|
Attribute::Cold.apply_llfn(Function, llfn);
|
||||||
}
|
}
|
||||||
|
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::FFI_RETURNS_TWICE) {
|
||||||
|
Attribute::ReturnsTwice.apply_llfn(Function, llfn);
|
||||||
|
}
|
||||||
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
|
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
|
||||||
naked(llfn, true);
|
naked(llfn, true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,6 +114,7 @@ pub enum Attribute {
|
||||||
SanitizeMemory = 22,
|
SanitizeMemory = 22,
|
||||||
NonLazyBind = 23,
|
NonLazyBind = 23,
|
||||||
OptimizeNone = 24,
|
OptimizeNone = 24,
|
||||||
|
ReturnsTwice = 25,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// LLVMIntPredicate
|
/// LLVMIntPredicate
|
||||||
|
|
|
@ -2388,6 +2388,18 @@ fn codegen_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> Codegen
|
||||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR;
|
codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR;
|
||||||
} else if attr.check_name("unwind") {
|
} else if attr.check_name("unwind") {
|
||||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::UNWIND;
|
codegen_fn_attrs.flags |= CodegenFnAttrFlags::UNWIND;
|
||||||
|
} else if attr.check_name("ffi_returns_twice") {
|
||||||
|
if tcx.is_foreign_item(id) {
|
||||||
|
codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_RETURNS_TWICE;
|
||||||
|
} else {
|
||||||
|
// `#[ffi_returns_twice]` is only allowed `extern fn`s
|
||||||
|
struct_span_err!(
|
||||||
|
tcx.sess,
|
||||||
|
attr.span,
|
||||||
|
E0723,
|
||||||
|
"`#[ffi_returns_twice]` may only be used on `extern fn`s"
|
||||||
|
).emit();
|
||||||
|
}
|
||||||
} else if attr.check_name("rustc_allocator_nounwind") {
|
} else if attr.check_name("rustc_allocator_nounwind") {
|
||||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_ALLOCATOR_NOUNWIND;
|
codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_ALLOCATOR_NOUNWIND;
|
||||||
} else if attr.check_name("naked") {
|
} else if attr.check_name("naked") {
|
||||||
|
|
|
@ -4738,4 +4738,5 @@ register_diagnostics! {
|
||||||
E0698, // type inside generator must be known in this context
|
E0698, // type inside generator must be known in this context
|
||||||
E0719, // duplicate values for associated type binding
|
E0719, // duplicate values for associated type binding
|
||||||
E0722, // Malformed #[optimize] attribute
|
E0722, // Malformed #[optimize] attribute
|
||||||
|
E0723, // `#[ffi_returns_twice]` is only allowed in `extern fn`
|
||||||
}
|
}
|
||||||
|
|
|
@ -290,6 +290,9 @@ declare_features! (
|
||||||
// The `repr(i128)` annotation for enums.
|
// The `repr(i128)` annotation for enums.
|
||||||
(active, repr128, "1.16.0", Some(35118), None),
|
(active, repr128, "1.16.0", Some(35118), None),
|
||||||
|
|
||||||
|
// Allows the use of `#[ffi_returns_twice]` on extern functions.
|
||||||
|
(active, ffi_returns_twice, "1.34.0", Some(58314), None),
|
||||||
|
|
||||||
// The `unadjusted` ABI; perma-unstable.
|
// The `unadjusted` ABI; perma-unstable.
|
||||||
//
|
//
|
||||||
// rustc internal
|
// rustc internal
|
||||||
|
@ -1128,6 +1131,11 @@ pub const BUILTIN_ATTRIBUTES: &[(&str, AttributeType, AttributeTemplate, Attribu
|
||||||
"the `#[naked]` attribute \
|
"the `#[naked]` attribute \
|
||||||
is an experimental feature",
|
is an experimental feature",
|
||||||
cfg_fn!(naked_functions))),
|
cfg_fn!(naked_functions))),
|
||||||
|
("ffi_returns_twice", Whitelisted, template!(Word), Gated(Stability::Unstable,
|
||||||
|
"ffi_returns_twice",
|
||||||
|
"the `#[ffi_returns_twice]` attribute \
|
||||||
|
is an experimental feature",
|
||||||
|
cfg_fn!(ffi_returns_twice))),
|
||||||
("target_feature", Whitelisted, template!(List: r#"enable = "name""#), Ungated),
|
("target_feature", Whitelisted, template!(List: r#"enable = "name""#), Ungated),
|
||||||
("export_name", Whitelisted, template!(NameValueStr: "name"), Ungated),
|
("export_name", Whitelisted, template!(NameValueStr: "name"), Ungated),
|
||||||
("inline", Whitelisted, template!(Word, List: "always|never"), Ungated),
|
("inline", Whitelisted, template!(Word, List: "always|never"), Ungated),
|
||||||
|
|
|
@ -190,6 +190,8 @@ static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) {
|
||||||
return Attribute::NonLazyBind;
|
return Attribute::NonLazyBind;
|
||||||
case OptimizeNone:
|
case OptimizeNone:
|
||||||
return Attribute::OptimizeNone;
|
return Attribute::OptimizeNone;
|
||||||
|
case ReturnsTwice:
|
||||||
|
return Attribute::ReturnsTwice;
|
||||||
}
|
}
|
||||||
report_fatal_error("bad AttributeKind");
|
report_fatal_error("bad AttributeKind");
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,6 +85,7 @@ enum LLVMRustAttribute {
|
||||||
SanitizeMemory = 22,
|
SanitizeMemory = 22,
|
||||||
NonLazyBind = 23,
|
NonLazyBind = 23,
|
||||||
OptimizeNone = 24,
|
OptimizeNone = 24,
|
||||||
|
ReturnsTwice = 25,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct OpaqueRustString *RustStringRef;
|
typedef struct OpaqueRustString *RustStringRef;
|
||||||
|
|
15
src/test/codegen/ffi-returns-twice.rs
Normal file
15
src/test/codegen/ffi-returns-twice.rs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
// compile-flags: -C no-prepopulate-passes
|
||||||
|
#![crate_type = "lib"]
|
||||||
|
#![feature(ffi_returns_twice)]
|
||||||
|
|
||||||
|
extern {
|
||||||
|
// CHECK-LABEL: @foo()
|
||||||
|
// CHECK: attributes #1 = { {{.*}}returns_twice{{.*}} }
|
||||||
|
#[no_mangle]
|
||||||
|
#[ffi_returns_twice]
|
||||||
|
pub fn foo();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn bar() {
|
||||||
|
unsafe { foo() }
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
// ignore-tidy-linelength
|
||||||
|
#![crate_type = "lib"]
|
||||||
|
|
||||||
|
extern {
|
||||||
|
#[ffi_returns_twice] //~ ERROR the `#[ffi_returns_twice]` attribute is an experimental feature (see issue #58314)
|
||||||
|
pub fn foo();
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
error[E0658]: the `#[ffi_returns_twice]` attribute is an experimental feature (see issue #58314)
|
||||||
|
--> $DIR/feature-gate-ffi_returns_twice.rs:5:5
|
||||||
|
|
|
||||||
|
LL | #[ffi_returns_twice] //~ ERROR the `#[ffi_returns_twice]` attribute is an experimental feature (see issue #58314)
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: add #![feature(ffi_returns_twice)] to the crate attributes to enable
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0658`.
|
6
src/test/ui/ffi_returns_twice.rs
Normal file
6
src/test/ui/ffi_returns_twice.rs
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
// ignore-tidy-linelength
|
||||||
|
#![feature(ffi_returns_twice)]
|
||||||
|
#![crate_type = "lib"]
|
||||||
|
|
||||||
|
#[ffi_returns_twice] //~ ERROR `#[ffi_returns_twice]` may only be used on `extern fn`s
|
||||||
|
pub fn foo() {}
|
9
src/test/ui/ffi_returns_twice.stderr
Normal file
9
src/test/ui/ffi_returns_twice.stderr
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
error[E0723]: `#[ffi_returns_twice]` may only be used on `extern fn`s
|
||||||
|
--> $DIR/ffi_returns_twice.rs:5:1
|
||||||
|
|
|
||||||
|
LL | #[ffi_returns_twice] //~ ERROR `#[ffi_returns_twice]` may only be used on `extern fn`s
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0723`.
|
Loading…
Add table
Reference in a new issue