@@ -2070,12 +2070,15 @@ pub fn get_fn_llvm_attributes(ccx: &CrateContext, fn_ty: ty::t)
2070
2070
// implications directly to the call instruction. Right now,
2071
2071
// the only attribute we need to worry about is `sret`.
2072
2072
if type_of:: return_uses_outptr( ccx, ret_ty) {
2073
+ let llret_sz = llsize_of_real( ccx, type_of:: type_of( ccx, ret_ty) ) ;
2074
+
2073
2075
// The outptr can be noalias and nocapture because it's entirely
2074
- // invisible to the program. We can also mark it as nonnull
2076
+ // invisible to the program. We also know it's nonnull as well
2077
+ // as how many bytes we can dereference
2075
2078
attrs. arg( 1 , llvm:: StructRetAttribute )
2076
2079
. arg( 1 , llvm:: NoAliasAttribute )
2077
2080
. arg( 1 , llvm:: NoCaptureAttribute )
2078
- . arg( 1 , llvm:: NonNullAttribute ) ;
2081
+ . arg( 1 , llvm:: DereferenceableAttribute ( llret_sz ) ) ;
2079
2082
2080
2083
// Add one more since there's an outptr
2081
2084
first_arg_offset += 1 ;
@@ -2094,15 +2097,16 @@ pub fn get_fn_llvm_attributes(ccx: &CrateContext, fn_ty: ty::t)
2094
2097
_ => { }
2095
2098
}
2096
2099
2097
- // We can also mark the return value as `nonnull ` in certain cases
2100
+ // We can also mark the return value as `dereferenceable ` in certain cases
2098
2101
match ty:: get( ret_ty) . sty {
2099
2102
// These are not really pointers but pairs, (pointer, len)
2100
2103
ty:: ty_uniq( it) |
2101
2104
ty:: ty_rptr( _, ty:: mt { ty: it, .. } ) if match ty:: get( it) . sty {
2102
2105
ty:: ty_str | ty:: ty_vec( ..) | ty:: ty_trait( ..) => true , _ => false
2103
2106
} => { }
2104
- ty:: ty_uniq( _) | ty:: ty_rptr( _, _) => {
2105
- attrs. ret( llvm:: NonNullAttribute ) ;
2107
+ ty:: ty_uniq( inner) | ty:: ty_rptr( _, ty:: mt { ty: inner, .. } ) => {
2108
+ let llret_sz = llsize_of_real( ccx, type_of:: type_of( ccx, inner) ) ;
2109
+ attrs. ret( llvm:: DereferenceableAttribute ( llret_sz) ) ;
2106
2110
}
2107
2111
_ => { }
2108
2112
}
@@ -2119,44 +2123,77 @@ pub fn get_fn_llvm_attributes(ccx: &CrateContext, fn_ty: ty::t)
2119
2123
match ty:: get( t) . sty {
2120
2124
// this needs to be first to prevent fat pointers from falling through
2121
2125
_ if !type_is_immediate( ccx, t) => {
2126
+ let llarg_sz = llsize_of_real( ccx, type_of:: type_of( ccx, t) ) ;
2127
+
2122
2128
// For non-immediate arguments the callee gets its own copy of
2123
2129
// the value on the stack, so there are no aliases. It's also
2124
2130
// program-invisible so can't possibly capture
2125
2131
attrs. arg( idx, llvm:: NoAliasAttribute )
2126
2132
. arg( idx, llvm:: NoCaptureAttribute )
2127
- . arg( idx, llvm:: NonNullAttribute ) ;
2133
+ . arg( idx, llvm:: DereferenceableAttribute ( llarg_sz ) ) ;
2128
2134
}
2135
+
2129
2136
ty:: ty_bool => {
2130
2137
attrs. arg( idx, llvm:: ZExtAttribute ) ;
2131
2138
}
2139
+
2132
2140
// `~` pointer parameters never alias because ownership is transferred
2133
- ty:: ty_uniq( _) => {
2141
+ ty:: ty_uniq( inner) => {
2142
+ let llsz = llsize_of_real( ccx, type_of:: type_of( ccx, inner) ) ;
2143
+
2144
+ attrs. arg( idx, llvm:: NoAliasAttribute )
2145
+ . arg( idx, llvm:: DereferenceableAttribute ( llsz) ) ;
2146
+ }
2147
+
2148
+ // The visit glue deals only with opaque pointers so we don't
2149
+ // actually know the concrete type of Self thus we don't know how
2150
+ // many bytes to mark as dereferenceable so instead we just mark
2151
+ // it as nonnull which still holds true
2152
+ ty:: ty_rptr( b, ty:: mt { ty: it, mutbl } ) if match ty:: get( it) . sty {
2153
+ ty:: ty_param( _) => true , _ => false
2154
+ } && mutbl == ast:: MutMutable => {
2134
2155
attrs. arg( idx, llvm:: NoAliasAttribute )
2135
2156
. arg( idx, llvm:: NonNullAttribute ) ;
2157
+
2158
+ match b {
2159
+ ReLateBound ( _, BrAnon ( _) ) => {
2160
+ attrs. arg( idx, llvm:: NoCaptureAttribute ) ;
2161
+ }
2162
+ _ => { }
2163
+ }
2136
2164
}
2165
+
2137
2166
// `&mut` pointer parameters never alias other parameters, or mutable global data
2138
2167
// `&` pointer parameters never alias either (for LLVM's purposes) as long as the
2139
2168
// interior is safe
2140
2169
ty:: ty_rptr( b, mt) if mt. mutbl == ast:: MutMutable ||
2141
2170
!ty:: type_contents( ccx. tcx( ) , mt. ty) . interior_unsafe( ) => {
2171
+
2172
+ let llsz = llsize_of_real( ccx, type_of:: type_of( ccx, mt. ty) ) ;
2142
2173
attrs. arg( idx, llvm:: NoAliasAttribute )
2143
- . arg( idx, llvm:: NonNullAttribute ) ;
2174
+ . arg( idx, llvm:: DereferenceableAttribute ( llsz) ) ;
2175
+
2144
2176
match b {
2145
2177
ReLateBound ( _, BrAnon ( _) ) => {
2146
2178
attrs. arg( idx, llvm:: NoCaptureAttribute ) ;
2147
2179
}
2148
2180
_ => { }
2149
2181
}
2150
2182
}
2183
+
2151
2184
// When a reference in an argument has no named lifetime, it's impossible for that
2152
2185
// reference to escape this function (returned or stored beyond the call by a closure).
2153
- ty:: ty_rptr( ReLateBound ( _, BrAnon ( _) ) , _) => {
2186
+ ty:: ty_rptr( ReLateBound ( _, BrAnon ( _) ) , mt) => {
2187
+ let llsz = llsize_of_real( ccx, type_of:: type_of( ccx, mt. ty) ) ;
2154
2188
attrs. arg( idx, llvm:: NoCaptureAttribute )
2155
- . arg( idx, llvm:: NonNullAttribute ) ;
2189
+ . arg( idx, llvm:: DereferenceableAttribute ( llsz ) ) ;
2156
2190
}
2157
- // & pointer parameters are never null
2158
- ty:: ty_rptr( _, _) => {
2159
- attrs. arg( idx, llvm:: NonNullAttribute ) ;
2191
+
2192
+ // & pointer parameters are also never null and we know exactly how
2193
+ // many bytes we can dereference
2194
+ ty:: ty_rptr( _, mt) => {
2195
+ let llsz = llsize_of_real( ccx, type_of:: type_of( ccx, mt. ty) ) ;
2196
+ attrs. arg( idx, llvm:: DereferenceableAttribute ( llsz) ) ;
2160
2197
}
2161
2198
_ => ( )
2162
2199
}
0 commit comments