From c4b46ace556f3e4776d06ea7672daba6b243a80f Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Sat, 9 Feb 2019 15:55:30 +0100 Subject: [PATCH 1/5] 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 d0b92587b59f0..df02b91996f34 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -2518,6 +2518,9 @@ bitflags! { /// `#[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 827ebff10f51c..dab5cab65cd02 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 e761d2247a757..fe2664118f798 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 ec1d9d24730ed..af029607638ad 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 3c4a0760f3ee2..eec2d39484947 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -4738,4 +4738,5 @@ register_diagnostics! { 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 d574b410ccc06..378e774686a48 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -290,6 +290,9 @@ declare_features! ( // 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 const BUILTIN_ATTRIBUTES: &[(&str, AttributeType, AttributeTemplate, Attribu "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 b33165b846339..a00417a362927 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 933266b402526..a9d267cdb3175 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 0000000000000..f6648249eb6e2 --- /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 0000000000000..d3df6e5a852b5 --- /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 0000000000000..5c111fe78f48a --- /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 0000000000000..5abf468febcef --- /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 0000000000000..4d3ca73af0283 --- /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`. From 52ba07dbe64c47f3255169f57474a5336c7a389d Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Sat, 9 Feb 2019 22:09:25 +0100 Subject: [PATCH 2/5] Correct error message --- src/librustc_typeck/collect.rs | 2 +- src/librustc_typeck/diagnostics.rs | 2 +- src/libsyntax/feature_gate.rs | 2 +- src/test/ui/ffi_returns_twice.rs | 2 +- src/test/ui/ffi_returns_twice.stderr | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index af029607638ad..1a03af4398dc2 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -2397,7 +2397,7 @@ fn codegen_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> Codegen tcx.sess, attr.span, E0723, - "`#[ffi_returns_twice]` may only be used on `extern fn`s" + "`#[ffi_returns_twice]` may only be used on foreign functions" ).emit(); } } else if attr.check_name("rustc_allocator_nounwind") { diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index eec2d39484947..6104c52141217 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -4738,5 +4738,5 @@ register_diagnostics! { 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` + E0723, // `#[ffi_returns_twice]` is only allowed in foreign functions } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 378e774686a48..c9b441193b76d 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -290,7 +290,7 @@ declare_features! ( // The `repr(i128)` annotation for enums. (active, repr128, "1.16.0", Some(35118), None), - // Allows the use of `#[ffi_returns_twice]` on extern functions. + // Allows the use of `#[ffi_returns_twice]` on foreign functions. (active, ffi_returns_twice, "1.34.0", Some(58314), None), // The `unadjusted` ABI; perma-unstable. diff --git a/src/test/ui/ffi_returns_twice.rs b/src/test/ui/ffi_returns_twice.rs index 5abf468febcef..93c372e1d83dc 100644 --- a/src/test/ui/ffi_returns_twice.rs +++ b/src/test/ui/ffi_returns_twice.rs @@ -2,5 +2,5 @@ #![feature(ffi_returns_twice)] #![crate_type = "lib"] -#[ffi_returns_twice] //~ ERROR `#[ffi_returns_twice]` may only be used on `extern fn`s +#[ffi_returns_twice] //~ ERROR `#[ffi_returns_twice]` may only be used on foreign functions pub fn foo() {} diff --git a/src/test/ui/ffi_returns_twice.stderr b/src/test/ui/ffi_returns_twice.stderr index 4d3ca73af0283..5a6026c403dae 100644 --- a/src/test/ui/ffi_returns_twice.stderr +++ b/src/test/ui/ffi_returns_twice.stderr @@ -1,7 +1,7 @@ -error[E0723]: `#[ffi_returns_twice]` may only be used on `extern fn`s +error[E0723]: `#[ffi_returns_twice]` may only be used on foreign functions --> $DIR/ffi_returns_twice.rs:5:1 | -LL | #[ffi_returns_twice] //~ ERROR `#[ffi_returns_twice]` may only be used on `extern fn`s +LL | #[ffi_returns_twice] //~ ERROR `#[ffi_returns_twice]` may only be used on foreign functions | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error From 76403e574231ae54dc7ccf227750af907ea13db3 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Sun, 10 Feb 2019 09:59:07 +0100 Subject: [PATCH 3/5] Use pattern to match attributes --- src/test/codegen/ffi-returns-twice.rs | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/test/codegen/ffi-returns-twice.rs b/src/test/codegen/ffi-returns-twice.rs index f6648249eb6e2..396e8990d6f88 100644 --- a/src/test/codegen/ffi-returns-twice.rs +++ b/src/test/codegen/ffi-returns-twice.rs @@ -2,14 +2,10 @@ #![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() } } -pub fn bar() { - unsafe { foo() } +extern { + #[ffi_returns_twice] pub fn foo(); } +// CHECK: declare void @foo(){{.*}}#1{{.*}} +// CHECK: attributes #1 = { {{.*}}returns_twice{{.*}} } From fcc0b3e398265f173bc668c11b87ca98b74185bd Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Sun, 10 Feb 2019 12:04:23 +0100 Subject: [PATCH 4/5] Fix attribute check --- src/test/codegen/ffi-returns-twice.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/test/codegen/ffi-returns-twice.rs b/src/test/codegen/ffi-returns-twice.rs index 396e8990d6f88..4db328f1cdfaf 100644 --- a/src/test/codegen/ffi-returns-twice.rs +++ b/src/test/codegen/ffi-returns-twice.rs @@ -5,7 +5,8 @@ pub fn bar() { unsafe { foo() } } extern { + // CHECK-LABEL: declare void @foo() + // CHECK-SAME: [[ATTRS:#[0-9]+]] + // CHECK-DAG: attributes [[ATTRS]] = { {{.*}}returns_twice{{.*}} } #[ffi_returns_twice] pub fn foo(); } -// CHECK: declare void @foo(){{.*}}#1{{.*}} -// CHECK: attributes #1 = { {{.*}}returns_twice{{.*}} } From 94aa74004efddf0cfb6fe4bb65eee9effbe40ae8 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Sat, 23 Feb 2019 16:24:14 +0100 Subject: [PATCH 5/5] Use E0724 instead of E0723 as an error code --- src/librustc_typeck/collect.rs | 2 +- src/librustc_typeck/diagnostics.rs | 2 +- src/test/ui/ffi_returns_twice.stderr | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 1a03af4398dc2..ba3df76050a8b 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -2396,7 +2396,7 @@ fn codegen_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> Codegen struct_span_err!( tcx.sess, attr.span, - E0723, + E0724, "`#[ffi_returns_twice]` may only be used on foreign functions" ).emit(); } diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 6104c52141217..caad342c138f0 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -4738,5 +4738,5 @@ register_diagnostics! { 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 foreign functions + E0724, // `#[ffi_returns_twice]` is only allowed in foreign functions } diff --git a/src/test/ui/ffi_returns_twice.stderr b/src/test/ui/ffi_returns_twice.stderr index 5a6026c403dae..c2105ae1dac7c 100644 --- a/src/test/ui/ffi_returns_twice.stderr +++ b/src/test/ui/ffi_returns_twice.stderr @@ -1,4 +1,4 @@ -error[E0723]: `#[ffi_returns_twice]` may only be used on foreign functions +error[E0724]: `#[ffi_returns_twice]` may only be used on foreign functions --> $DIR/ffi_returns_twice.rs:5:1 | LL | #[ffi_returns_twice] //~ ERROR `#[ffi_returns_twice]` may only be used on foreign functions @@ -6,4 +6,4 @@ LL | #[ffi_returns_twice] //~ ERROR `#[ffi_returns_twice]` may only be used on f error: aborting due to previous error -For more information about this error, try `rustc --explain E0723`. +For more information about this error, try `rustc --explain E0724`.