@@ -274,6 +274,7 @@ fn layout_of<'tcx>(
274
274
} )
275
275
}
276
276
277
+ #[ derive( Clone , Copy ) ]
277
278
pub struct LayoutCx < ' tcx , C > {
278
279
pub tcx : C ,
279
280
pub param_env : ty:: ParamEnv < ' tcx > ,
@@ -3074,6 +3075,93 @@ fn fn_abi_of_instance<'tcx>(
3074
3075
)
3075
3076
}
3076
3077
3078
+ // Handle safe Rust thin and fat pointers.
3079
+ pub fn adjust_for_rust_scalar < ' tcx > (
3080
+ cx : LayoutCx < ' tcx , TyCtxt < ' tcx > > ,
3081
+ attrs : & mut ArgAttributes ,
3082
+ scalar : Scalar ,
3083
+ layout : TyAndLayout < ' tcx > ,
3084
+ offset : Size ,
3085
+ is_return : bool ,
3086
+ ) {
3087
+ // Booleans are always a noundef i1 that needs to be zero-extended.
3088
+ if scalar. is_bool ( ) {
3089
+ attrs. ext ( ArgExtension :: Zext ) ;
3090
+ attrs. set ( ArgAttribute :: NoUndef ) ;
3091
+ return ;
3092
+ }
3093
+
3094
+ // Scalars which have invalid values cannot be undef.
3095
+ if !scalar. is_always_valid ( & cx) {
3096
+ attrs. set ( ArgAttribute :: NoUndef ) ;
3097
+ }
3098
+
3099
+ // Only pointer types handled below.
3100
+ let Scalar :: Initialized { value : Pointer , valid_range} = scalar else { return } ;
3101
+
3102
+ if !valid_range. contains ( 0 ) {
3103
+ attrs. set ( ArgAttribute :: NonNull ) ;
3104
+ }
3105
+
3106
+ if let Some ( pointee) = layout. pointee_info_at ( & cx, offset) {
3107
+ if let Some ( kind) = pointee. safe {
3108
+ attrs. pointee_align = Some ( pointee. align ) ;
3109
+
3110
+ // `Box` (`UniqueBorrowed`) are not necessarily dereferenceable
3111
+ // for the entire duration of the function as they can be deallocated
3112
+ // at any time. Same for shared mutable references. If LLVM had a
3113
+ // way to say "dereferenceable on entry" we could use it here.
3114
+ attrs. pointee_size = match kind {
3115
+ PointerKind :: UniqueBorrowed
3116
+ | PointerKind :: UniqueBorrowedPinned
3117
+ | PointerKind :: Frozen => pointee. size ,
3118
+ PointerKind :: SharedMutable | PointerKind :: UniqueOwned => Size :: ZERO ,
3119
+ } ;
3120
+
3121
+ // `Box`, `&T`, and `&mut T` cannot be undef.
3122
+ // Note that this only applies to the value of the pointer itself;
3123
+ // this attribute doesn't make it UB for the pointed-to data to be undef.
3124
+ attrs. set ( ArgAttribute :: NoUndef ) ;
3125
+
3126
+ // The aliasing rules for `Box<T>` are still not decided, but currently we emit
3127
+ // `noalias` for it. This can be turned off using an unstable flag.
3128
+ // See https://github.com/rust-lang/unsafe-code-guidelines/issues/326
3129
+ let noalias_for_box = cx. tcx . sess . opts . unstable_opts . box_noalias . unwrap_or ( true ) ;
3130
+
3131
+ // `&mut` pointer parameters never alias other parameters,
3132
+ // or mutable global data
3133
+ //
3134
+ // `&T` where `T` contains no `UnsafeCell<U>` is immutable,
3135
+ // and can be marked as both `readonly` and `noalias`, as
3136
+ // LLVM's definition of `noalias` is based solely on memory
3137
+ // dependencies rather than pointer equality
3138
+ //
3139
+ // Due to past miscompiles in LLVM, we apply a separate NoAliasMutRef attribute
3140
+ // for UniqueBorrowed arguments, so that the codegen backend can decide whether
3141
+ // or not to actually emit the attribute. It can also be controlled with the
3142
+ // `-Zmutable-noalias` debugging option.
3143
+ let no_alias = match kind {
3144
+ PointerKind :: SharedMutable
3145
+ | PointerKind :: UniqueBorrowed
3146
+ | PointerKind :: UniqueBorrowedPinned => false ,
3147
+ PointerKind :: UniqueOwned => noalias_for_box,
3148
+ PointerKind :: Frozen => !is_return,
3149
+ } ;
3150
+ if no_alias {
3151
+ attrs. set ( ArgAttribute :: NoAlias ) ;
3152
+ }
3153
+
3154
+ if kind == PointerKind :: Frozen && !is_return {
3155
+ attrs. set ( ArgAttribute :: ReadOnly ) ;
3156
+ }
3157
+
3158
+ if kind == PointerKind :: UniqueBorrowed && !is_return {
3159
+ attrs. set ( ArgAttribute :: NoAliasMutRef ) ;
3160
+ }
3161
+ }
3162
+ }
3163
+ }
3164
+
3077
3165
impl < ' tcx > LayoutCx < ' tcx , TyCtxt < ' tcx > > {
3078
3166
// FIXME(eddyb) perhaps group the signature/type-containing (or all of them?)
3079
3167
// arguments of this method, into a separate `struct`.
@@ -3129,91 +3217,6 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
3129
3217
use SpecAbi :: * ;
3130
3218
let rust_abi = matches ! ( sig. abi, RustIntrinsic | PlatformIntrinsic | Rust | RustCall ) ;
3131
3219
3132
- // Handle safe Rust thin and fat pointers.
3133
- let adjust_for_rust_scalar = |attrs : & mut ArgAttributes ,
3134
- scalar : Scalar ,
3135
- layout : TyAndLayout < ' tcx > ,
3136
- offset : Size ,
3137
- is_return : bool | {
3138
- // Booleans are always a noundef i1 that needs to be zero-extended.
3139
- if scalar. is_bool ( ) {
3140
- attrs. ext ( ArgExtension :: Zext ) ;
3141
- attrs. set ( ArgAttribute :: NoUndef ) ;
3142
- return ;
3143
- }
3144
-
3145
- // Scalars which have invalid values cannot be undef.
3146
- if !scalar. is_always_valid ( self ) {
3147
- attrs. set ( ArgAttribute :: NoUndef ) ;
3148
- }
3149
-
3150
- // Only pointer types handled below.
3151
- let Scalar :: Initialized { value : Pointer , valid_range} = scalar else { return } ;
3152
-
3153
- if !valid_range. contains ( 0 ) {
3154
- attrs. set ( ArgAttribute :: NonNull ) ;
3155
- }
3156
-
3157
- if let Some ( pointee) = layout. pointee_info_at ( self , offset) {
3158
- if let Some ( kind) = pointee. safe {
3159
- attrs. pointee_align = Some ( pointee. align ) ;
3160
-
3161
- // `Box` (`UniqueBorrowed`) are not necessarily dereferenceable
3162
- // for the entire duration of the function as they can be deallocated
3163
- // at any time. Same for shared mutable references. If LLVM had a
3164
- // way to say "dereferenceable on entry" we could use it here.
3165
- attrs. pointee_size = match kind {
3166
- PointerKind :: UniqueBorrowed
3167
- | PointerKind :: UniqueBorrowedPinned
3168
- | PointerKind :: Frozen => pointee. size ,
3169
- PointerKind :: SharedMutable | PointerKind :: UniqueOwned => Size :: ZERO ,
3170
- } ;
3171
-
3172
- // `Box`, `&T`, and `&mut T` cannot be undef.
3173
- // Note that this only applies to the value of the pointer itself;
3174
- // this attribute doesn't make it UB for the pointed-to data to be undef.
3175
- attrs. set ( ArgAttribute :: NoUndef ) ;
3176
-
3177
- // The aliasing rules for `Box<T>` are still not decided, but currently we emit
3178
- // `noalias` for it. This can be turned off using an unstable flag.
3179
- // See https://github.com/rust-lang/unsafe-code-guidelines/issues/326
3180
- let noalias_for_box =
3181
- self . tcx ( ) . sess . opts . unstable_opts . box_noalias . unwrap_or ( true ) ;
3182
-
3183
- // `&mut` pointer parameters never alias other parameters,
3184
- // or mutable global data
3185
- //
3186
- // `&T` where `T` contains no `UnsafeCell<U>` is immutable,
3187
- // and can be marked as both `readonly` and `noalias`, as
3188
- // LLVM's definition of `noalias` is based solely on memory
3189
- // dependencies rather than pointer equality
3190
- //
3191
- // Due to past miscompiles in LLVM, we apply a separate NoAliasMutRef attribute
3192
- // for UniqueBorrowed arguments, so that the codegen backend can decide whether
3193
- // or not to actually emit the attribute. It can also be controlled with the
3194
- // `-Zmutable-noalias` debugging option.
3195
- let no_alias = match kind {
3196
- PointerKind :: SharedMutable
3197
- | PointerKind :: UniqueBorrowed
3198
- | PointerKind :: UniqueBorrowedPinned => false ,
3199
- PointerKind :: UniqueOwned => noalias_for_box,
3200
- PointerKind :: Frozen => !is_return,
3201
- } ;
3202
- if no_alias {
3203
- attrs. set ( ArgAttribute :: NoAlias ) ;
3204
- }
3205
-
3206
- if kind == PointerKind :: Frozen && !is_return {
3207
- attrs. set ( ArgAttribute :: ReadOnly ) ;
3208
- }
3209
-
3210
- if kind == PointerKind :: UniqueBorrowed && !is_return {
3211
- attrs. set ( ArgAttribute :: NoAliasMutRef ) ;
3212
- }
3213
- }
3214
- }
3215
- } ;
3216
-
3217
3220
let arg_of = |ty : Ty < ' tcx > , arg_idx : Option < usize > | -> Result < _ , FnAbiError < ' tcx > > {
3218
3221
let is_return = arg_idx. is_none ( ) ;
3219
3222
@@ -3229,7 +3232,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
3229
3232
3230
3233
let mut arg = ArgAbi :: new ( self , layout, |layout, scalar, offset| {
3231
3234
let mut attrs = ArgAttributes :: new ( ) ;
3232
- adjust_for_rust_scalar ( & mut attrs, scalar, * layout, offset, is_return) ;
3235
+ adjust_for_rust_scalar ( * self , & mut attrs, scalar, * layout, offset, is_return) ;
3233
3236
attrs
3234
3237
} ) ;
3235
3238
0 commit comments