@@ -281,7 +281,11 @@ pub fn decl_rust_fn(ccx: &CrateContext, fn_ty: ty::t, name: &str) -> ValueRef {
281
281
282
282
let llfn = decl_fn ( ccx, name, llvm:: CCallConv , llfty, output) ;
283
283
let attrs = get_fn_llvm_attributes ( ccx, fn_ty) ;
284
- attrs. apply_llfn ( llfn) ;
284
+ for & ( idx, attr) in attrs. iter ( ) {
285
+ unsafe {
286
+ llvm:: LLVMAddFunctionAttribute ( llfn, idx as c_uint , attr) ;
287
+ }
288
+ }
285
289
286
290
llfn
287
291
}
@@ -958,7 +962,7 @@ pub fn invoke<'a>(
958
962
llargs. as_slice ( ) ,
959
963
normal_bcx. llbb ,
960
964
landing_pad,
961
- Some ( attributes) ) ;
965
+ attributes. as_slice ( ) ) ;
962
966
return ( llresult, normal_bcx) ;
963
967
} else {
964
968
debug ! ( "calling {} at {}" , llfn, bcx. llbb) ;
@@ -971,7 +975,7 @@ pub fn invoke<'a>(
971
975
None => debuginfo:: clear_source_location ( bcx. fcx )
972
976
} ;
973
977
974
- let llresult = Call ( bcx, llfn, llargs. as_slice ( ) , Some ( attributes) ) ;
978
+ let llresult = Call ( bcx, llfn, llargs. as_slice ( ) , attributes. as_slice ( ) ) ;
975
979
return ( llresult, bcx) ;
976
980
}
977
981
}
@@ -1077,7 +1081,7 @@ pub fn call_lifetime_start(cx: &Block, ptr: ValueRef) {
1077
1081
let llsize = C_u64 ( ccx, machine:: llsize_of_alloc ( ccx, val_ty ( ptr) . element_type ( ) ) ) ;
1078
1082
let ptr = PointerCast ( cx, ptr, Type :: i8p ( ccx) ) ;
1079
1083
let lifetime_start = ccx. get_intrinsic ( & "llvm.lifetime.start" ) ;
1080
- Call ( cx, lifetime_start, [ llsize, ptr] , None ) ;
1084
+ Call ( cx, lifetime_start, [ llsize, ptr] , [ ] ) ;
1081
1085
}
1082
1086
1083
1087
pub fn call_lifetime_end ( cx : & Block , ptr : ValueRef ) {
@@ -1091,7 +1095,7 @@ pub fn call_lifetime_end(cx: &Block, ptr: ValueRef) {
1091
1095
let llsize = C_u64 ( ccx, machine:: llsize_of_alloc ( ccx, val_ty ( ptr) . element_type ( ) ) ) ;
1092
1096
let ptr = PointerCast ( cx, ptr, Type :: i8p ( ccx) ) ;
1093
1097
let lifetime_end = ccx. get_intrinsic ( & "llvm.lifetime.end" ) ;
1094
- Call ( cx, lifetime_end, [ llsize, ptr] , None ) ;
1098
+ Call ( cx, lifetime_end, [ llsize, ptr] , [ ] ) ;
1095
1099
}
1096
1100
1097
1101
pub fn call_memcpy ( cx : & Block , dst : ValueRef , src : ValueRef , n_bytes : ValueRef , align : u32 ) {
@@ -1107,7 +1111,7 @@ pub fn call_memcpy(cx: &Block, dst: ValueRef, src: ValueRef, n_bytes: ValueRef,
1107
1111
let size = IntCast ( cx, n_bytes, ccx. int_type ) ;
1108
1112
let align = C_i32 ( ccx, align as i32 ) ;
1109
1113
let volatile = C_bool ( ccx, false ) ;
1110
- Call ( cx, memcpy, [ dst_ptr, src_ptr, size, align, volatile] , None ) ;
1114
+ Call ( cx, memcpy, [ dst_ptr, src_ptr, size, align, volatile] , [ ] ) ;
1111
1115
}
1112
1116
1113
1117
pub fn memcpy_ty ( bcx : & Block , dst : ValueRef , src : ValueRef , t : ty:: t ) {
@@ -1152,7 +1156,7 @@ fn memzero(b: &Builder, llptr: ValueRef, ty: Type) {
1152
1156
let size = machine:: llsize_of ( ccx, ty) ;
1153
1157
let align = C_i32 ( ccx, llalign_of_min ( ccx, ty) as i32 ) ;
1154
1158
let volatile = C_bool ( ccx, false ) ;
1155
- b. call ( llintrinsicfn, [ llptr, llzeroval, size, align, volatile] , None ) ;
1159
+ b. call ( llintrinsicfn, [ llptr, llzeroval, size, align, volatile] , [ ] ) ;
1156
1160
}
1157
1161
1158
1162
pub fn alloc_ty ( bcx : & Block , t : ty:: t , name : & str ) -> ValueRef {
@@ -2036,7 +2040,7 @@ fn register_fn(ccx: &CrateContext,
2036
2040
}
2037
2041
2038
2042
pub fn get_fn_llvm_attributes( ccx: & CrateContext , fn_ty: ty:: t)
2039
- -> llvm :: AttrBuilder {
2043
+ -> Vec < ( uint , u64 ) > {
2040
2044
use middle:: ty:: { BrAnon , ReLateBound } ;
2041
2045
2042
2046
let ( fn_sig, abi, has_env) = match ty:: get( fn_ty) . sty {
@@ -2052,33 +2056,31 @@ pub fn get_fn_llvm_attributes(ccx: &CrateContext, fn_ty: ty::t)
2052
2056
_ => fail!( "expected closure or function." )
2053
2057
} ;
2054
2058
2055
- // Since index 0 is the return value of the llvm func, we start
2056
- // at either 1 or 2 depending on whether there's an env slot or not
2057
- let mut first_arg_offset = if has_env { 2 } else { 1 } ;
2058
- let mut attrs = llvm:: AttrBuilder :: new( ) ;
2059
- let ret_ty = fn_sig. output;
2060
-
2061
2059
// These have an odd calling convention, so we skip them for now.
2062
2060
//
2063
2061
// FIXME(pcwalton): We don't have to skip them; just untuple the result.
2064
2062
if abi == RustCall {
2065
- return attrs ;
2063
+ return Vec :: new ( )
2066
2064
}
2067
2065
2066
+ // Since index 0 is the return value of the llvm func, we start
2067
+ // at either 1 or 2 depending on whether there's an env slot or not
2068
+ let mut first_arg_offset = if has_env { 2 } else { 1 } ;
2069
+ let mut attrs = Vec :: new( ) ;
2070
+ let ret_ty = fn_sig. output;
2071
+
2068
2072
// A function pointer is called without the declaration
2069
2073
// available, so we have to apply any attributes with ABI
2070
2074
// implications directly to the call instruction. Right now,
2071
2075
// the only attribute we need to worry about is `sret`.
2072
2076
if type_of:: return_uses_outptr( ccx, ret_ty) {
2073
- let llret_sz = llsize_of_real ( ccx , type_of :: type_of ( ccx , ret_ty ) ) ;
2077
+ attrs . push ( ( 1 , llvm :: StructRetAttribute as u64 ) ) ;
2074
2078
2075
2079
// The outptr can be noalias and nocapture because it's entirely
2076
- // invisible to the program. We also know it's nonnull as well
2077
- // as how many bytes we can dereference
2078
- attrs. arg( 1 , llvm:: StructRetAttribute )
2079
- . arg( 1 , llvm:: NoAliasAttribute )
2080
- . arg( 1 , llvm:: NoCaptureAttribute )
2081
- . arg( 1 , llvm:: DereferenceableAttribute ( llret_sz) ) ;
2080
+ // invisible to the program. We can also mark it as nonnull
2081
+ attrs. push( ( 1 , llvm:: NoAliasAttribute as u64 ) ) ;
2082
+ attrs. push( ( 1 , llvm:: NoCaptureAttribute as u64 ) ) ;
2083
+ attrs. push( ( 1 , llvm:: NonNullAttribute as u64 ) ) ;
2082
2084
2083
2085
// Add one more since there's an outptr
2084
2086
first_arg_offset += 1 ;
@@ -2092,28 +2094,27 @@ pub fn get_fn_llvm_attributes(ccx: &CrateContext, fn_ty: ty::t)
2092
2094
ty:: ty_str | ty:: ty_vec( ..) | ty:: ty_trait( ..) => true , _ => false
2093
2095
} => { }
2094
2096
ty:: ty_uniq( _) => {
2095
- attrs. ret ( llvm:: NoAliasAttribute ) ;
2097
+ attrs. push ( ( llvm:: ReturnIndex as uint , llvm :: NoAliasAttribute as u64 ) ) ;
2096
2098
}
2097
2099
_ => { }
2098
2100
}
2099
2101
2100
- // We can also mark the return value as `dereferenceable ` in certain cases
2102
+ // We can also mark the return value as `nonnull ` in certain cases
2101
2103
match ty:: get( ret_ty) . sty {
2102
2104
// These are not really pointers but pairs, (pointer, len)
2103
2105
ty:: ty_uniq( it) |
2104
2106
ty:: ty_rptr( _, ty:: mt { ty: it, .. } ) if match ty:: get( it) . sty {
2105
2107
ty:: ty_str | ty:: ty_vec( ..) | ty:: ty_trait( ..) => true , _ => false
2106
2108
} => { }
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) ) ;
2109
+ ty:: ty_uniq( _) | ty:: ty_rptr( _, _) => {
2110
+ attrs. push( ( llvm:: ReturnIndex as uint, llvm:: NonNullAttribute as u64 ) ) ;
2110
2111
}
2111
2112
_ => { }
2112
2113
}
2113
2114
2114
2115
match ty:: get( ret_ty) . sty {
2115
2116
ty:: ty_bool => {
2116
- attrs. ret ( llvm:: ZExtAttribute ) ;
2117
+ attrs. push ( ( llvm:: ReturnIndex as uint , llvm :: ZExtAttribute as u64 ) ) ;
2117
2118
}
2118
2119
_ => { }
2119
2120
}
@@ -2123,77 +2124,44 @@ pub fn get_fn_llvm_attributes(ccx: &CrateContext, fn_ty: ty::t)
2123
2124
match ty:: get( t) . sty {
2124
2125
// this needs to be first to prevent fat pointers from falling through
2125
2126
_ if !type_is_immediate( ccx, t) => {
2126
- let llarg_sz = llsize_of_real( ccx, type_of:: type_of( ccx, t) ) ;
2127
-
2128
2127
// For non-immediate arguments the callee gets its own copy of
2129
2128
// the value on the stack, so there are no aliases. It's also
2130
2129
// program-invisible so can't possibly capture
2131
- attrs. arg ( idx, llvm:: NoAliasAttribute )
2132
- . arg ( idx, llvm:: NoCaptureAttribute )
2133
- . arg ( idx, llvm:: DereferenceableAttribute ( llarg_sz ) ) ;
2130
+ attrs. push ( ( idx, llvm:: NoAliasAttribute as u64 ) ) ;
2131
+ attrs . push ( ( idx, llvm:: NoCaptureAttribute as u64 ) ) ;
2132
+ attrs . push ( ( idx, llvm:: NonNullAttribute as u64 ) ) ;
2134
2133
}
2135
-
2136
2134
ty:: ty_bool => {
2137
- attrs. arg ( idx, llvm:: ZExtAttribute ) ;
2135
+ attrs. push ( ( idx, llvm:: ZExtAttribute as u64 ) ) ;
2138
2136
}
2139
-
2140
2137
// `~` pointer parameters never alias because ownership is transferred
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 => {
2155
- attrs. arg( idx, llvm:: NoAliasAttribute )
2156
- . arg( idx, llvm:: NonNullAttribute ) ;
2157
-
2158
- match b {
2159
- ReLateBound ( _, BrAnon ( _) ) => {
2160
- attrs. arg( idx, llvm:: NoCaptureAttribute ) ;
2161
- }
2162
- _ => { }
2163
- }
2138
+ ty:: ty_uniq( _) => {
2139
+ attrs. push( ( idx, llvm:: NoAliasAttribute as u64 ) ) ;
2140
+ attrs. push( ( idx, llvm:: NonNullAttribute as u64 ) ) ;
2164
2141
}
2165
-
2166
2142
// `&mut` pointer parameters never alias other parameters, or mutable global data
2167
2143
// `&` pointer parameters never alias either (for LLVM's purposes) as long as the
2168
2144
// interior is safe
2169
2145
ty:: ty_rptr( b, mt) if mt. mutbl == ast:: MutMutable ||
2170
2146
!ty:: type_contents( ccx. tcx( ) , mt. ty) . interior_unsafe( ) => {
2171
-
2172
- let llsz = llsize_of_real( ccx, type_of:: type_of( ccx, mt. ty) ) ;
2173
- attrs. arg( idx, llvm:: NoAliasAttribute )
2174
- . arg( idx, llvm:: DereferenceableAttribute ( llsz) ) ;
2175
-
2147
+ attrs. push( ( idx, llvm:: NoAliasAttribute as u64 ) ) ;
2148
+ attrs. push( ( idx, llvm:: NonNullAttribute as u64 ) ) ;
2176
2149
match b {
2177
2150
ReLateBound ( _, BrAnon ( _) ) => {
2178
- attrs. arg ( idx, llvm:: NoCaptureAttribute ) ;
2151
+ attrs. push ( ( idx, llvm:: NoCaptureAttribute as u64 ) ) ;
2179
2152
}
2180
2153
_ => { }
2181
2154
}
2182
2155
}
2183
-
2184
2156
// When a reference in an argument has no named lifetime, it's impossible for that
2185
2157
// reference to escape this function (returned or stored beyond the call by a closure).
2186
- ty:: ty_rptr( ReLateBound ( _, BrAnon ( _) ) , mt) => {
2187
- let llsz = llsize_of_real( ccx, type_of:: type_of( ccx, mt. ty) ) ;
2188
- attrs. arg( idx, llvm:: NoCaptureAttribute )
2189
- . arg( idx, llvm:: DereferenceableAttribute ( llsz) ) ;
2158
+ ty:: ty_rptr( ReLateBound ( _, BrAnon ( _) ) , _) => {
2159
+ attrs. push( ( idx, llvm:: NoCaptureAttribute as u64 ) ) ;
2160
+ attrs. push( ( idx, llvm:: NonNullAttribute as u64 ) ) ;
2190
2161
}
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) ) ;
2162
+ // & pointer parameters are never null
2163
+ ty:: ty_rptr( _, _) => {
2164
+ attrs. push( ( idx, llvm:: NonNullAttribute as u64 ) ) ;
2197
2165
}
2198
2166
_ => ( )
2199
2167
}
0 commit comments