@@ -274,6 +274,7 @@ fn layout_of<'tcx>(
274274 } )
275275}
276276
277+ #[ derive( Clone , Copy ) ]
277278pub struct LayoutCx < ' tcx , C > {
278279 pub tcx : C ,
279280 pub param_env : ty:: ParamEnv < ' tcx > ,
@@ -3074,6 +3075,93 @@ fn fn_abi_of_instance<'tcx>(
30743075 )
30753076}
30763077
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+
30773165impl < ' tcx > LayoutCx < ' tcx , TyCtxt < ' tcx > > {
30783166 // FIXME(eddyb) perhaps group the signature/type-containing (or all of them?)
30793167 // arguments of this method, into a separate `struct`.
@@ -3129,91 +3217,6 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
31293217 use SpecAbi :: * ;
31303218 let rust_abi = matches ! ( sig. abi, RustIntrinsic | PlatformIntrinsic | Rust | RustCall ) ;
31313219
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-
32173220 let arg_of = |ty : Ty < ' tcx > , arg_idx : Option < usize > | -> Result < _ , FnAbiError < ' tcx > > {
32183221 let is_return = arg_idx. is_none ( ) ;
32193222
@@ -3229,7 +3232,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
32293232
32303233 let mut arg = ArgAbi :: new ( self , layout, |layout, scalar, offset| {
32313234 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) ;
32333236 attrs
32343237 } ) ;
32353238
0 commit comments