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