Skip to content

Commit 9b0ae75

Browse files
maurernebulark
authored andcommitted
Support #[patchable_function_entries]
See [RFC](https://github.com/maurer/rust-rfcs/blob/patchable-function-entry/text/0000-patchable-function-entry.md) (yet to be numbered) TODO before submission: * Needs an RFC * Improve error reporting for malformed attributes
1 parent ac7595f commit 9b0ae75

File tree

9 files changed

+83
-4
lines changed

9 files changed

+83
-4
lines changed

compiler/rustc_codegen_llvm/src/attributes.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
use rustc_codegen_ssa::traits::*;
44
use rustc_hir::def_id::DefId;
5-
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
5+
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, PatchableFunctionEntry};
66
use rustc_middle::ty::{self, TyCtxt};
77
use rustc_session::config::{FunctionReturn, OptLevel};
88
use rustc_span::symbol::sym;
@@ -56,9 +56,12 @@ fn inline_attr<'ll>(cx: &CodegenCx<'ll, '_>, inline: InlineAttr) -> Option<&'ll
5656
#[inline]
5757
fn patchable_function_entry_attrs<'ll>(
5858
cx: &CodegenCx<'ll, '_>,
59+
attr: Option<PatchableFunctionEntry>,
5960
) -> SmallVec<[&'ll Attribute; 2]> {
6061
let mut attrs = SmallVec::new();
61-
let patchable_spec = cx.tcx.sess.opts.unstable_opts.patchable_function_entry;
62+
let patchable_spec = attr.unwrap_or_else(|| {
63+
PatchableFunctionEntry::from_config(cx.tcx.sess.opts.unstable_opts.patchable_function_entry)
64+
});
6265
let entry = patchable_spec.entry();
6366
let prefix = patchable_spec.prefix();
6467
if entry > 0 {
@@ -446,7 +449,7 @@ pub fn from_fn_attrs<'ll, 'tcx>(
446449
llvm::set_alignment(llfn, align);
447450
}
448451
to_add.extend(sanitize_attrs(cx, codegen_fn_attrs.no_sanitize));
449-
to_add.extend(patchable_function_entry_attrs(cx));
452+
to_add.extend(patchable_function_entry_attrs(cx, codegen_fn_attrs.patchable_function_entry));
450453

451454
// Always annotate functions with the target-cpu they are compiled for.
452455
// Without this, ThinLTO won't inline Rust functions into Clang generated

compiler/rustc_codegen_ssa/src/codegen_attrs.rs

+25-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ use rustc_hir as hir;
55
use rustc_hir::def::DefKind;
66
use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
77
use rustc_hir::{lang_items, weak_lang_items::WEAK_LANG_ITEMS, LangItem};
8-
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
8+
use rustc_middle::middle::codegen_fn_attrs::{
9+
CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry,
10+
};
911
use rustc_middle::mir::mono::Linkage;
1012
use rustc_middle::query::Providers;
1113
use rustc_middle::ty::{self as ty, TyCtxt};
@@ -463,6 +465,28 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
463465
None
464466
};
465467
}
468+
sym::patchable_function_entry => {
469+
codegen_fn_attrs.patchable_function_entry = attr.meta_item_list().and_then(|l| {
470+
let mut prefix = 0;
471+
let mut entry = 0;
472+
for item in l {
473+
if let Some((sym, lit)) = item.name_value_literal() {
474+
let val = match lit.kind {
475+
// FIXME emit error if too many nops requested
476+
rustc_ast::LitKind::Int(i, _) => i as u8,
477+
_ => continue,
478+
};
479+
match sym {
480+
sym::prefix => prefix = val,
481+
sym::entry => entry = val,
482+
// FIXME possibly emit error here?
483+
_ => continue,
484+
}
485+
}
486+
}
487+
Some(PatchableFunctionEntry::from_prefix_and_entry(prefix, entry))
488+
})
489+
}
466490
_ => {}
467491
}
468492
}

compiler/rustc_feature/src/builtin_attrs.rs

+7
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,13 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
584584
pointee, Normal, template!(Word), ErrorFollowing,
585585
EncodeCrossCrate::No, derive_smart_pointer, experimental!(pointee)
586586
),
587+
588+
// FIXME RFC
589+
// `#[patchable_function_entry(prefix(n), entry(n))]`
590+
gated!(
591+
patchable_function_entry, Normal, template!(List: "prefix(n), entry(n)"), ErrorPreceding,
592+
experimental!(patchable_function_entry)
593+
),
587594

588595
// ==========================================================================
589596
// Internal attributes: Stability, deprecation, and unsafe:

compiler/rustc_feature/src/unstable.rs

+3
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,9 @@ declare_features! (
565565
(unstable, offset_of_slice, "CURRENT_RUSTC_VERSION", Some(126151)),
566566
/// Allows using `#[optimize(X)]`.
567567
(unstable, optimize_attribute, "1.34.0", Some(54882)),
568+
/// Allows specifying nop padding on functions for dynamic patching.
569+
// FIXME this needs an RFC #
570+
(unstable, patchable_function_entry, "CURRENT_RUSTC_VERSION", Some(9999)),
568571
/// Allows postfix match `expr.match { ... }`
569572
(unstable, postfix_match, "1.79.0", Some(121618)),
570573
/// Allows `use<'a, 'b, A, B>` in `impl Trait + use<...>` for precise capture of generic args.

compiler/rustc_middle/src/middle/codegen_fn_attrs.rs

+4
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ pub struct CodegenFnAttrs {
4545
/// The `#[repr(align(...))]` attribute. Indicates the value of which the function should be
4646
/// aligned to.
4747
pub alignment: Option<Align>,
48+
/// The `#[patchable_function_entry(...)]` attribute. Indicates how many nops should be around
49+
/// the function entry.
50+
pub patchable_function_entry: Option<PatchableFunctionEntry>,
4851
}
4952

5053
#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
@@ -147,6 +150,7 @@ impl CodegenFnAttrs {
147150
no_sanitize: SanitizerSet::empty(),
148151
instruction_set: None,
149152
alignment: None,
153+
patchable_function_entry: None,
150154
}
151155
}
152156

compiler/rustc_span/src/symbol.rs

+3
Original file line numberDiff line numberDiff line change
@@ -768,6 +768,7 @@ symbols! {
768768
enable,
769769
encode,
770770
end,
771+
entry,
771772
enumerate_method,
772773
env,
773774
env_CFG_RELEASE: env!("CFG_RELEASE"),
@@ -1383,6 +1384,7 @@ symbols! {
13831384
passes,
13841385
pat,
13851386
pat_param,
1387+
patchable_function_entry,
13861388
path,
13871389
pattern_complexity,
13881390
pattern_parentheses,
@@ -1421,6 +1423,7 @@ symbols! {
14211423
prefetch_read_instruction,
14221424
prefetch_write_data,
14231425
prefetch_write_instruction,
1426+
prefix,
14241427
preg,
14251428
prelude,
14261429
prelude_import,
+20
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,28 @@
1+
#![feature(patchable_function_entry)]
12
// compile-flags: -Z patchable-function-entry=15,10
23

34
#![crate_type = "lib"]
45

6+
// This should have the default, as set by the compile flags
57
#[no_mangle]
68
pub fn foo() {}
9+
10+
// The attribute should override the compile flags
11+
#[no_mangle]
12+
#[patchable_function_entry(prefix(1), entry(2))]
13+
pub fn bar() {}
14+
15+
// If we override an attribute to 0 or unset, the attribute should go away
16+
#[no_mangle]
17+
#[patchable_function_entry(entry(0))]
18+
pub fn baz() {}
19+
720
// CHECK: @foo() unnamed_addr #0
21+
// CHECK: @bar() unnamed_addr #1
22+
// CHECK: @baz() unnamed_addr #2
23+
824
// CHECK: attributes #0 = { {{.*}}"patchable-function-entry"="5"{{.*}}"patchable-function-prefix"="10" {{.*}} }
25+
// CHECK: attributes #1 = { {{.*}}"patchable-function-entry"="2"{{.*}}"patchable-function-prefix"="1" {{.*}} }
26+
// CHECK-NOT: attributes #2 = { {{.*}}patchable-function-entry{{.*}} }
27+
// CHECK-NOT: attributes #2 = { {{.*}}patchable-function-prefix{{.*}} }
28+
// CHECK: attributes #2 = { {{.*}} }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#[patchable_function_entry(entry(1), prefix(1))]
2+
//~^ ERROR: the `#[patchable_function_entry]` attribute is an experimental feature
3+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0658]: the `#[patchable_function_entry]` attribute is an experimental feature
2+
--> $DIR/feature-gate-patchable-function-entry.rs:1:1
3+
|
4+
LL | #[patchable_function_entry(entry(1), prefix(1))]
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: see issue #9999 <https://github.com/rust-lang/rust/issues/9999> for more information
8+
= help: add `#![feature(patchable_function_entry)]` to the crate attributes to enable
9+
10+
error: aborting due to 1 previous error
11+
12+
For more information about this error, try `rustc --explain E0658`.

0 commit comments

Comments
 (0)