提交 c4b46ace 编写于 作者: G gnzlbg

Implement ffi_returns_twice attribute

上级 bcfb5e8a
......@@ -2518,6 +2518,9 @@ pub struct CodegenFnAttrFlags: u32 {
/// `#[used]`: indicates that LLVM can't eliminate this function (but the
/// linker can!).
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) {
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) {
naked(llfn, true);
}
......
......@@ -114,6 +114,7 @@ pub enum Attribute {
SanitizeMemory = 22,
NonLazyBind = 23,
OptimizeNone = 24,
ReturnsTwice = 25,
}
/// 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;
} else if attr.check_name("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") {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_ALLOCATOR_NOUNWIND;
} else if attr.check_name("naked") {
......
......@@ -4738,4 +4738,5 @@ fn make_recursive_type() -> impl Sized {
E0698, // type inside generator must be known in this context
E0719, // duplicate values for associated type binding
E0722, // Malformed #[optimize] attribute
E0723, // `#[ffi_returns_twice]` is only allowed in `extern fn`
}
......@@ -290,6 +290,9 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
// The `repr(i128)` annotation for enums.
(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.
//
// rustc internal
......@@ -1128,6 +1131,11 @@ pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
"the `#[naked]` attribute \
is an experimental feature",
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),
("export_name", Whitelisted, template!(NameValueStr: "name"), Ungated),
("inline", Whitelisted, template!(Word, List: "always|never"), Ungated),
......
......@@ -190,6 +190,8 @@ static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) {
return Attribute::NonLazyBind;
case OptimizeNone:
return Attribute::OptimizeNone;
case ReturnsTwice:
return Attribute::ReturnsTwice;
}
report_fatal_error("bad AttributeKind");
}
......
......@@ -85,6 +85,7 @@ enum LLVMRustAttribute {
SanitizeMemory = 22,
NonLazyBind = 23,
OptimizeNone = 24,
ReturnsTwice = 25,
};
typedef struct OpaqueRustString *RustStringRef;
......
// 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() }
}
// 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();
}
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`.
// 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() {}
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`.
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册