Skip to content

Commit

Permalink
Implement ffi_returns_twice attribute
Browse files Browse the repository at this point in the history
  • Loading branch information
gnzlbg committed Feb 23, 2019
1 parent bcfb5e8 commit c4b46ac
Show file tree
Hide file tree
Showing 13 changed files with 79 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/librustc/hir/mod.rs
Expand Up @@ -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;
}
}

Expand Down
3 changes: 3 additions & 0 deletions src/librustc_codegen_llvm/attributes.rs
Expand Up @@ -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);
}
Expand Down
1 change: 1 addition & 0 deletions src/librustc_codegen_llvm/llvm/ffi.rs
Expand Up @@ -114,6 +114,7 @@ pub enum Attribute {
SanitizeMemory = 22,
NonLazyBind = 23,
OptimizeNone = 24,
ReturnsTwice = 25,
}

/// LLVMIntPredicate
Expand Down
12 changes: 12 additions & 0 deletions src/librustc_typeck/collect.rs
Expand Up @@ -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") {
Expand Down
1 change: 1 addition & 0 deletions src/librustc_typeck/diagnostics.rs
Expand Up @@ -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`
}
8 changes: 8 additions & 0 deletions src/libsyntax/feature_gate.rs
Expand Up @@ -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
Expand Down Expand Up @@ -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),
Expand Down
2 changes: 2 additions & 0 deletions src/rustllvm/RustWrapper.cpp
Expand Up @@ -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");
}
Expand Down
1 change: 1 addition & 0 deletions src/rustllvm/rustllvm.h
Expand Up @@ -85,6 +85,7 @@ enum LLVMRustAttribute {
SanitizeMemory = 22,
NonLazyBind = 23,
OptimizeNone = 24,
ReturnsTwice = 25,
};

typedef struct OpaqueRustString *RustStringRef;
Expand Down
15 changes: 15 additions & 0 deletions 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() }
}
7 changes: 7 additions & 0 deletions 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();
}
11 changes: 11 additions & 0 deletions 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`.
6 changes: 6 additions & 0 deletions 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() {}
9 changes: 9 additions & 0 deletions 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`.

0 comments on commit c4b46ac

Please sign in to comment.