From c4b46ace556f3e4776d06ea7672daba6b243a80f Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Sat, 9 Feb 2019 15:55:30 +0100 Subject: [PATCH] Implement ffi_returns_twice attribute --- src/librustc/hir/mod.rs | 3 +++ src/librustc_codegen_llvm/attributes.rs | 3 +++ src/librustc_codegen_llvm/llvm/ffi.rs | 1 + src/librustc_typeck/collect.rs | 12 ++++++++++++ src/librustc_typeck/diagnostics.rs | 1 + src/libsyntax/feature_gate.rs | 8 ++++++++ src/rustllvm/RustWrapper.cpp | 2 ++ src/rustllvm/rustllvm.h | 1 + src/test/codegen/ffi-returns-twice.rs | 15 +++++++++++++++ .../feature-gate-ffi_returns_twice.rs | 7 +++++++ .../feature-gate-ffi_returns_twice.stderr | 11 +++++++++++ src/test/ui/ffi_returns_twice.rs | 6 ++++++ src/test/ui/ffi_returns_twice.stderr | 9 +++++++++ 13 files changed, 79 insertions(+) create mode 100644 src/test/codegen/ffi-returns-twice.rs create mode 100644 src/test/ui/feature-gates/feature-gate-ffi_returns_twice.rs create mode 100644 src/test/ui/feature-gates/feature-gate-ffi_returns_twice.stderr create mode 100644 src/test/ui/ffi_returns_twice.rs create mode 100644 src/test/ui/ffi_returns_twice.stderr diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index d0b92587b59..df02b91996f 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -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; } } diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs index 827ebff10f5..dab5cab65cd 100644 --- a/src/librustc_codegen_llvm/attributes.rs +++ b/src/librustc_codegen_llvm/attributes.rs @@ -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); } diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs index e761d2247a7..fe2664118f7 100644 --- a/src/librustc_codegen_llvm/llvm/ffi.rs +++ b/src/librustc_codegen_llvm/llvm/ffi.rs @@ -114,6 +114,7 @@ pub enum Attribute { SanitizeMemory = 22, NonLazyBind = 23, OptimizeNone = 24, + ReturnsTwice = 25, } /// LLVMIntPredicate diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index ec1d9d24730..af029607638 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -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") { diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 3c4a0760f3e..eec2d394849 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -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` } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index d574b410ccc..378e774686a 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -290,6 +290,9 @@ pub fn walk_feature_fields(&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), diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index b33165b8463..a00417a3629 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -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"); } diff --git a/src/rustllvm/rustllvm.h b/src/rustllvm/rustllvm.h index 933266b4025..a9d267cdb31 100644 --- a/src/rustllvm/rustllvm.h +++ b/src/rustllvm/rustllvm.h @@ -85,6 +85,7 @@ enum LLVMRustAttribute { SanitizeMemory = 22, NonLazyBind = 23, OptimizeNone = 24, + ReturnsTwice = 25, }; typedef struct OpaqueRustString *RustStringRef; diff --git a/src/test/codegen/ffi-returns-twice.rs b/src/test/codegen/ffi-returns-twice.rs new file mode 100644 index 00000000000..f6648249eb6 --- /dev/null +++ b/src/test/codegen/ffi-returns-twice.rs @@ -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() } +} diff --git a/src/test/ui/feature-gates/feature-gate-ffi_returns_twice.rs b/src/test/ui/feature-gates/feature-gate-ffi_returns_twice.rs new file mode 100644 index 00000000000..d3df6e5a852 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-ffi_returns_twice.rs @@ -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(); +} diff --git a/src/test/ui/feature-gates/feature-gate-ffi_returns_twice.stderr b/src/test/ui/feature-gates/feature-gate-ffi_returns_twice.stderr new file mode 100644 index 00000000000..5c111fe78f4 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-ffi_returns_twice.stderr @@ -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`. diff --git a/src/test/ui/ffi_returns_twice.rs b/src/test/ui/ffi_returns_twice.rs new file mode 100644 index 00000000000..5abf468febc --- /dev/null +++ b/src/test/ui/ffi_returns_twice.rs @@ -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() {} diff --git a/src/test/ui/ffi_returns_twice.stderr b/src/test/ui/ffi_returns_twice.stderr new file mode 100644 index 00000000000..4d3ca73af02 --- /dev/null +++ b/src/test/ui/ffi_returns_twice.stderr @@ -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`. -- GitLab