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