Skip to content

Commit 097c04c

Browse files
committed
Auto merge of #58315 - gnzlbg:returns_twice, r=alexcrichton
Implement unstable ffi_return_twice attribute This PR implements [RFC2633](rust-lang/rfcs#2633) r? @eddyb
2 parents e17c48e + 94aa740 commit 097c04c

File tree

13 files changed

+76
-0
lines changed

13 files changed

+76
-0
lines changed

src/librustc/hir/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -2518,6 +2518,9 @@ bitflags! {
25182518
/// `#[used]`: indicates that LLVM can't eliminate this function (but the
25192519
/// linker can!).
25202520
const USED = 1 << 9;
2521+
/// #[ffi_returns_twice], indicates that an extern function can return
2522+
/// multiple times
2523+
const FFI_RETURNS_TWICE = 1 << 10;
25212524
}
25222525
}
25232526

src/librustc_codegen_llvm/attributes.rs

+3
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,9 @@ pub fn from_fn_attrs(
223223
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::COLD) {
224224
Attribute::Cold.apply_llfn(Function, llfn);
225225
}
226+
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::FFI_RETURNS_TWICE) {
227+
Attribute::ReturnsTwice.apply_llfn(Function, llfn);
228+
}
226229
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
227230
naked(llfn, true);
228231
}

src/librustc_codegen_llvm/llvm/ffi.rs

+1
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ pub enum Attribute {
114114
SanitizeMemory = 22,
115115
NonLazyBind = 23,
116116
OptimizeNone = 24,
117+
ReturnsTwice = 25,
117118
}
118119

119120
/// LLVMIntPredicate

src/librustc_typeck/collect.rs

+12
Original file line numberDiff line numberDiff line change
@@ -2388,6 +2388,18 @@ fn codegen_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> Codegen
23882388
codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR;
23892389
} else if attr.check_name("unwind") {
23902390
codegen_fn_attrs.flags |= CodegenFnAttrFlags::UNWIND;
2391+
} else if attr.check_name("ffi_returns_twice") {
2392+
if tcx.is_foreign_item(id) {
2393+
codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_RETURNS_TWICE;
2394+
} else {
2395+
// `#[ffi_returns_twice]` is only allowed `extern fn`s
2396+
struct_span_err!(
2397+
tcx.sess,
2398+
attr.span,
2399+
E0724,
2400+
"`#[ffi_returns_twice]` may only be used on foreign functions"
2401+
).emit();
2402+
}
23912403
} else if attr.check_name("rustc_allocator_nounwind") {
23922404
codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_ALLOCATOR_NOUNWIND;
23932405
} else if attr.check_name("naked") {

src/librustc_typeck/diagnostics.rs

+1
Original file line numberDiff line numberDiff line change
@@ -4738,4 +4738,5 @@ register_diagnostics! {
47384738
E0698, // type inside generator must be known in this context
47394739
E0719, // duplicate values for associated type binding
47404740
E0722, // Malformed #[optimize] attribute
4741+
E0724, // `#[ffi_returns_twice]` is only allowed in foreign functions
47414742
}

src/libsyntax/feature_gate.rs

+8
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,9 @@ declare_features! (
290290
// The `repr(i128)` annotation for enums.
291291
(active, repr128, "1.16.0", Some(35118), None),
292292

293+
// Allows the use of `#[ffi_returns_twice]` on foreign functions.
294+
(active, ffi_returns_twice, "1.34.0", Some(58314), None),
295+
293296
// The `unadjusted` ABI; perma-unstable.
294297
//
295298
// rustc internal
@@ -1128,6 +1131,11 @@ pub const BUILTIN_ATTRIBUTES: &[(&str, AttributeType, AttributeTemplate, Attribu
11281131
"the `#[naked]` attribute \
11291132
is an experimental feature",
11301133
cfg_fn!(naked_functions))),
1134+
("ffi_returns_twice", Whitelisted, template!(Word), Gated(Stability::Unstable,
1135+
"ffi_returns_twice",
1136+
"the `#[ffi_returns_twice]` attribute \
1137+
is an experimental feature",
1138+
cfg_fn!(ffi_returns_twice))),
11311139
("target_feature", Whitelisted, template!(List: r#"enable = "name""#), Ungated),
11321140
("export_name", Whitelisted, template!(NameValueStr: "name"), Ungated),
11331141
("inline", Whitelisted, template!(Word, List: "always|never"), Ungated),

src/rustllvm/RustWrapper.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,8 @@ static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) {
190190
return Attribute::NonLazyBind;
191191
case OptimizeNone:
192192
return Attribute::OptimizeNone;
193+
case ReturnsTwice:
194+
return Attribute::ReturnsTwice;
193195
}
194196
report_fatal_error("bad AttributeKind");
195197
}

src/rustllvm/rustllvm.h

+1
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ enum LLVMRustAttribute {
8585
SanitizeMemory = 22,
8686
NonLazyBind = 23,
8787
OptimizeNone = 24,
88+
ReturnsTwice = 25,
8889
};
8990

9091
typedef struct OpaqueRustString *RustStringRef;

src/test/codegen/ffi-returns-twice.rs

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// compile-flags: -C no-prepopulate-passes
2+
#![crate_type = "lib"]
3+
#![feature(ffi_returns_twice)]
4+
5+
pub fn bar() { unsafe { foo() } }
6+
7+
extern {
8+
// CHECK-LABEL: declare void @foo()
9+
// CHECK-SAME: [[ATTRS:#[0-9]+]]
10+
// CHECK-DAG: attributes [[ATTRS]] = { {{.*}}returns_twice{{.*}} }
11+
#[ffi_returns_twice] pub fn foo();
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// ignore-tidy-linelength
2+
#![crate_type = "lib"]
3+
4+
extern {
5+
#[ffi_returns_twice] //~ ERROR the `#[ffi_returns_twice]` attribute is an experimental feature (see issue #58314)
6+
pub fn foo();
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0658]: the `#[ffi_returns_twice]` attribute is an experimental feature (see issue #58314)
2+
--> $DIR/feature-gate-ffi_returns_twice.rs:5:5
3+
|
4+
LL | #[ffi_returns_twice] //~ ERROR the `#[ffi_returns_twice]` attribute is an experimental feature (see issue #58314)
5+
| ^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= help: add #![feature(ffi_returns_twice)] to the crate attributes to enable
8+
9+
error: aborting due to previous error
10+
11+
For more information about this error, try `rustc --explain E0658`.

src/test/ui/ffi_returns_twice.rs

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// ignore-tidy-linelength
2+
#![feature(ffi_returns_twice)]
3+
#![crate_type = "lib"]
4+
5+
#[ffi_returns_twice] //~ ERROR `#[ffi_returns_twice]` may only be used on foreign functions
6+
pub fn foo() {}

src/test/ui/ffi_returns_twice.stderr

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0724]: `#[ffi_returns_twice]` may only be used on foreign functions
2+
--> $DIR/ffi_returns_twice.rs:5:1
3+
|
4+
LL | #[ffi_returns_twice] //~ ERROR `#[ffi_returns_twice]` may only be used on foreign functions
5+
| ^^^^^^^^^^^^^^^^^^^^
6+
7+
error: aborting due to previous error
8+
9+
For more information about this error, try `rustc --explain E0724`.

0 commit comments

Comments
 (0)