Skip to content

Commit 1b8f2e4

Browse files
committed
Auto merge of #155207 - quiode:writable, r=RalfJung
add llvm writable attribute conditionally This PR tries to address rust-lang/unsafe-code-guidelines#584 (comment). It is part of a bachelor thesis supervised by @JoJoDeveloping and @RalfJung, for more information, see: [Project_Description.pdf](https://github.com/user-attachments/files/26537277/Project_Description.pdf). If the new `-Zllvm-writable` flag is set, the [llvm writable attribute](https://llvm.org/docs/LangRef.html#writable) is inserted for all mutable borrows. This can be conditionally turned off on a per-function basis using the `#[rustc_no_writable]` attribute. The new Undefined Behaviour introduced by this can detected by Miri, which is implemented here: rust-lang/miri#4947. Two library functions already received the `#[rustc_no_writable]` attribute, as they are known to cause problems under the Tree Borrows aliasing model with implicit writes enabled.
2 parents 0204aca + da2bbfb commit 1b8f2e4

16 files changed

Lines changed: 95 additions & 4 deletions

File tree

compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,21 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcNoMirInlineParser {
527527
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNoMirInline;
528528
}
529529

530+
pub(crate) struct RustcNoWritableParser;
531+
532+
impl<S: Stage> NoArgsAttributeParser<S> for RustcNoWritableParser {
533+
const PATH: &[Symbol] = &[sym::rustc_no_writable];
534+
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
535+
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
536+
Allow(Target::Fn),
537+
Allow(Target::Closure),
538+
Allow(Target::Method(MethodKind::Inherent)),
539+
Allow(Target::Method(MethodKind::TraitImpl)),
540+
Allow(Target::Method(MethodKind::Trait { body: true })),
541+
]);
542+
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNoWritable;
543+
}
544+
530545
pub(crate) struct RustcLintQueryInstabilityParser;
531546

532547
impl<S: Stage> NoArgsAttributeParser<S> for RustcLintQueryInstabilityParser {

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,7 @@ attribute_parsers!(
314314
Single<WithoutArgs<RustcNoImplicitAutorefsParser>>,
315315
Single<WithoutArgs<RustcNoImplicitBoundsParser>>,
316316
Single<WithoutArgs<RustcNoMirInlineParser>>,
317+
Single<WithoutArgs<RustcNoWritableParser>>,
317318
Single<WithoutArgs<RustcNonConstTraitMethodParser>>,
318319
Single<WithoutArgs<RustcNonnullOptimizationGuaranteedParser>>,
319320
Single<WithoutArgs<RustcNounwindParser>>,

compiler/rustc_codegen_llvm/src/abi.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,12 @@ trait ArgAttributesExt {
3838
const ABI_AFFECTING_ATTRIBUTES: [(ArgAttribute, llvm::AttributeKind); 1] =
3939
[(ArgAttribute::InReg, llvm::AttributeKind::InReg)];
4040

41-
const OPTIMIZATION_ATTRIBUTES: [(ArgAttribute, llvm::AttributeKind); 4] = [
41+
const OPTIMIZATION_ATTRIBUTES: [(ArgAttribute, llvm::AttributeKind); 5] = [
4242
(ArgAttribute::NoAlias, llvm::AttributeKind::NoAlias),
4343
(ArgAttribute::NonNull, llvm::AttributeKind::NonNull),
4444
(ArgAttribute::ReadOnly, llvm::AttributeKind::ReadOnly),
4545
(ArgAttribute::NoUndef, llvm::AttributeKind::NoUndef),
46+
(ArgAttribute::Writable, llvm::AttributeKind::Writable),
4647
];
4748

4849
const CAPTURES_ATTRIBUTES: [(ArgAttribute, llvm::AttributeKind); 3] = [

compiler/rustc_feature/src/builtin_attrs.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -955,6 +955,10 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
955955
rustc_must_match_exhaustively,
956956
"enums with `#[rustc_must_match_exhaustively]` must be matched on with a match block that mentions all variants explicitly"
957957
),
958+
rustc_attr!(
959+
rustc_no_writable,
960+
"`#[rustc_no_writable]` stops the compiler from considering mutable reference arguments of this function as implicitly writable"
961+
),
958962

959963
// ==========================================================================
960964
// Internal attributes, Testing:

compiler/rustc_hir/src/attrs/data_structures.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1506,6 +1506,9 @@ pub enum AttributeKind {
15061506
/// Represents `#[rustc_no_mir_inline]`
15071507
RustcNoMirInline,
15081508

1509+
/// Represents `#[rustc_no_writable]`
1510+
RustcNoWritable,
1511+
15091512
/// Represents `#[rustc_non_const_trait_method]`.
15101513
RustcNonConstTraitMethod,
15111514

compiler/rustc_hir/src/attrs/encode_cross_crate.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ impl AttributeKind {
163163
RustcNoImplicitAutorefs => Yes,
164164
RustcNoImplicitBounds => No,
165165
RustcNoMirInline => Yes,
166+
RustcNoWritable => Yes,
166167
RustcNonConstTraitMethod => No, // should be reported via other queries like `constness`
167168
RustcNonnullOptimizationGuaranteed => Yes,
168169
RustcNounwind => No,

compiler/rustc_interface/src/tests.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -817,6 +817,7 @@ fn test_unstable_options_tracking_hash() {
817817
tracked!(lint_llvm_ir, true);
818818
tracked!(llvm_module_flag, vec![("bar".to_string(), 123, "max".to_string())]);
819819
tracked!(llvm_plugins, vec![String::from("plugin_name")]);
820+
tracked!(llvm_writable, true);
820821
tracked!(location_detail, LocationDetail { file: true, line: false, column: false });
821822
tracked!(maximal_hir_to_mir_coverage, true);
822823
tracked!(merge_functions, Some(MergeFunctions::Disabled));

compiler/rustc_passes/src/check_attr.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
350350
| AttributeKind::RustcNoImplicitAutorefs
351351
| AttributeKind::RustcNoImplicitBounds
352352
| AttributeKind::RustcNoMirInline
353+
| AttributeKind::RustcNoWritable
353354
| AttributeKind::RustcNonConstTraitMethod
354355
| AttributeKind::RustcNonnullOptimizationGuaranteed
355356
| AttributeKind::RustcNounwind

compiler/rustc_session/src/options.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2604,6 +2604,8 @@ options! {
26042604
"a list LLVM plugins to enable (space separated)"),
26052605
llvm_time_trace: bool = (false, parse_bool, [UNTRACKED],
26062606
"generate JSON tracing data file from LLVM data (default: no)"),
2607+
llvm_writable: bool = (false, parse_bool, [TRACKED],
2608+
"emit the LLVM writable attribute for mutable reference arguments (default: no)"),
26072609
location_detail: LocationDetail = (LocationDetail::all(), parse_location_detail, [TRACKED],
26082610
"what location details should be tracked when using caller_location, either \
26092611
`none`, or a comma separated list of location details, for which \

compiler/rustc_span/src/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1769,6 +1769,7 @@ symbols! {
17691769
rustc_no_implicit_autorefs,
17701770
rustc_no_implicit_bounds,
17711771
rustc_no_mir_inline,
1772+
rustc_no_writable,
17721773
rustc_non_const_trait_method,
17731774
rustc_nonnull_optimization_guaranteed,
17741775
rustc_nounwind,

0 commit comments

Comments
 (0)