@@ -263,6 +263,7 @@ fn layout_of<'tcx>(
263263 Ok ( layout)
264264}
265265
266+ #[ derive( Clone , Copy ) ]
266267pub struct LayoutCx < ' tcx , C > {
267268 pub tcx : C ,
268269 pub param_env : ty:: ParamEnv < ' tcx > ,
@@ -3063,6 +3064,93 @@ fn fn_abi_of_instance<'tcx>(
30633064 )
30643065}
30653066
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+
30663154impl < ' tcx > LayoutCx < ' tcx , TyCtxt < ' tcx > > {
30673155 // FIXME(eddyb) perhaps group the signature/type-containing (or all of them?)
30683156 // arguments of this method, into a separate `struct`.
@@ -3118,91 +3206,6 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
31183206 use SpecAbi :: * ;
31193207 let rust_abi = matches ! ( sig. abi, RustIntrinsic | PlatformIntrinsic | Rust | RustCall ) ;
31203208
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-
32063209 let arg_of = |ty : Ty < ' tcx > , arg_idx : Option < usize > | -> Result < _ , FnAbiError < ' tcx > > {
32073210 let is_return = arg_idx. is_none ( ) ;
32083211
@@ -3218,7 +3221,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
32183221
32193222 let mut arg = ArgAbi :: new ( self , layout, |layout, scalar, offset| {
32203223 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) ;
32223225 attrs
32233226 } ) ;
32243227
0 commit comments