@@ -26,6 +26,7 @@ use middle::traits::ProjectionMode;
26
26
use syntax:: abi:: Abi ;
27
27
use trans:: attributes;
28
28
use trans:: base;
29
+ use trans:: cabi:: FnType ;
29
30
use trans:: context:: CrateContext ;
30
31
use trans:: type_:: Type ;
31
32
use trans:: type_of;
@@ -51,8 +52,6 @@ pub fn declare_global(ccx: &CrateContext, name: &str, ty: Type) -> llvm::ValueRe
51
52
52
53
/// Declare a function.
53
54
///
54
- /// For rust functions use `declare_rust_fn` instead.
55
- ///
56
55
/// If there’s a value with the same name already declared, the function will
57
56
/// update the declaration and return existing ValueRef instead.
58
57
fn declare_raw_fn ( ccx : & CrateContext , name : & str , callconv : llvm:: CallConv , ty : Type ) -> ValueRef {
@@ -81,7 +80,7 @@ fn declare_raw_fn(ccx: &CrateContext, name: &str, callconv: llvm::CallConv, ty:
81
80
/// Declare a C ABI function.
82
81
///
83
82
/// Only use this for foreign function ABIs and glue. For Rust functions use
84
- /// `declare_rust_fn ` instead.
83
+ /// `declare_fn ` instead.
85
84
///
86
85
/// If there’s a value with the same name already declared, the function will
87
86
/// update the declaration and return existing ValueRef instead.
@@ -94,8 +93,8 @@ pub fn declare_cfn(ccx: &CrateContext, name: &str, fn_type: Type) -> ValueRef {
94
93
///
95
94
/// If there’s a value with the same name already declared, the function will
96
95
/// update the declaration and return existing ValueRef instead.
97
- pub fn declare_rust_fn < ' a , ' tcx > ( ccx : & CrateContext < ' a , ' tcx > , name : & str ,
98
- fn_type : ty:: Ty < ' tcx > ) -> ValueRef {
96
+ pub fn declare_fn < ' a , ' tcx > ( ccx : & CrateContext < ' a , ' tcx > , name : & str ,
97
+ fn_type : ty:: Ty < ' tcx > ) -> ValueRef {
99
98
debug ! ( "declare_rust_fn(name={:?}, fn_type={:?})" , name,
100
99
fn_type) ;
101
100
@@ -118,28 +117,33 @@ pub fn declare_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str,
118
117
_ => ccx. sess ( ) . bug ( "expected closure or fn" )
119
118
} ;
120
119
120
+
121
121
let sig = ccx. tcx ( ) . erase_late_bound_regions ( sig) ;
122
122
let sig = infer:: normalize_associated_type ( ccx. tcx ( ) , & sig) ;
123
123
debug ! ( "declare_rust_fn (after region erasure) sig={:?}" , sig) ;
124
- let llfty = type_of:: type_of_rust_fn ( ccx, env, & sig, abi) ;
125
- debug ! ( "declare_rust_fn llfty={:?}" , llfty) ;
124
+
125
+ let ( cconv, llfty) = if abi == Abi :: Rust || abi == Abi :: RustCall {
126
+ ( llvm:: CCallConv , type_of:: type_of_rust_fn ( ccx, env, & sig, abi) )
127
+ } else {
128
+ let fty = FnType :: new ( ccx, abi, & sig, & [ ] ) ;
129
+ ( fty. cconv , fty. to_llvm ( ccx) )
130
+ } ;
126
131
127
132
// it is ok to directly access sig.0.output because we erased all
128
133
// late-bound-regions above
129
- let llfn = declare_fn ( ccx, name, llvm:: CCallConv , llfty, sig. output ) ;
130
- attributes:: from_fn_type ( ccx, fn_type) . apply_llfn ( llfn) ;
131
- llfn
132
- }
134
+ debug ! ( "declare_rust_fn llfty={:?}" , llfty) ;
135
+ let llfn = declare_raw_fn ( ccx, name, cconv, llfty) ;
133
136
137
+ if sig. output == ty:: FnDiverging {
138
+ llvm:: SetFunctionAttribute ( llfn, llvm:: Attribute :: NoReturn ) ;
139
+ }
140
+
141
+ if abi == Abi :: Rust || abi == Abi :: RustCall {
142
+ attributes:: from_fn_type ( ccx, fn_type) . apply_llfn ( llfn) ;
143
+ } else {
144
+ FnType :: new ( ccx, abi, & sig, & [ ] ) . add_attributes ( llfn) ;
145
+ }
134
146
135
- /// Declare a Rust function with internal linkage.
136
- ///
137
- /// If there’s a value with the same name already declared, the function will
138
- /// update the declaration and return existing ValueRef instead.
139
- pub fn declare_internal_rust_fn < ' a , ' tcx > ( ccx : & CrateContext < ' a , ' tcx > , name : & str ,
140
- fn_type : ty:: Ty < ' tcx > ) -> ValueRef {
141
- let llfn = declare_rust_fn ( ccx, name, fn_type) ;
142
- llvm:: SetLinkage ( llfn, llvm:: InternalLinkage ) ;
143
147
llfn
144
148
}
145
149
@@ -159,71 +163,20 @@ pub fn define_global(ccx: &CrateContext, name: &str, ty: Type) -> Option<ValueRe
159
163
}
160
164
161
165
162
- /// Declare a function with an intention to define it.
163
- ///
164
- /// For rust functions use `define_rust_fn` instead.
165
- ///
166
- /// Use this function when you intend to define a function. This function will
167
- /// return None if the name already has a definition associated with it. In that
168
- /// case an error should be reported to the user, because it usually happens due
169
- /// to user’s fault (e.g. misuse of #[no_mangle] or #[export_name] attributes).
170
- pub fn define_fn ( ccx : & CrateContext , name : & str , callconv : llvm:: CallConv ,
171
- fn_type : Type , output : ty:: FnOutput ) -> Option < ValueRef > {
172
- if get_defined_value ( ccx, name) . is_some ( ) {
173
- None
174
- } else {
175
- Some ( declare_fn ( ccx, name, callconv, fn_type, output) )
176
- }
177
- }
178
-
179
-
180
- /// Declare a C ABI function with an intention to define it.
181
- ///
182
- /// Use this function when you intend to define a function. This function will
183
- /// return None if the name already has a definition associated with it. In that
184
- /// case an error should be reported to the user, because it usually happens due
185
- /// to user’s fault (e.g. misuse of #[no_mangle] or #[export_name] attributes).
186
- ///
187
- /// Only use this for foreign function ABIs and glue. For Rust functions use
188
- /// `declare_rust_fn` instead.
189
- pub fn define_cfn ( ccx : & CrateContext , name : & str , fn_type : Type ,
190
- output : ty:: Ty ) -> Option < ValueRef > {
191
- if get_defined_value ( ccx, name) . is_some ( ) {
192
- None
193
- } else {
194
- Some ( declare_cfn ( ccx, name, fn_type, output) )
195
- }
196
- }
197
-
198
-
199
- /// Declare a Rust function with an intention to define it.
200
- ///
201
- /// Use this function when you intend to define a function. This function will
202
- /// return None if the name already has a definition associated with it. In that
203
- /// case an error should be reported to the user, because it usually happens due
204
- /// to user’s fault (e.g. misuse of #[no_mangle] or #[export_name] attributes).
205
- pub fn define_rust_fn < ' a , ' tcx > ( ccx : & CrateContext < ' a , ' tcx > , name : & str ,
206
- fn_type : ty:: Ty < ' tcx > ) -> Option < ValueRef > {
207
- if get_defined_value ( ccx, name) . is_some ( ) {
208
- None
209
- } else {
210
- Some ( declare_rust_fn ( ccx, name, fn_type) )
211
- }
212
- }
213
-
214
-
215
166
/// Declare a Rust function with an intention to define it.
216
167
///
217
168
/// Use this function when you intend to define a function. This function will
218
169
/// return panic if the name already has a definition associated with it. This
219
170
/// can happen with #[no_mangle] or #[export_name], for example.
220
- pub fn define_internal_rust_fn < ' a , ' tcx > ( ccx : & CrateContext < ' a , ' tcx > ,
221
- name : & str ,
222
- fn_type : ty:: Ty < ' tcx > ) -> ValueRef {
171
+ pub fn define_internal_fn < ' a , ' tcx > ( ccx : & CrateContext < ' a , ' tcx > ,
172
+ name : & str ,
173
+ fn_type : ty:: Ty < ' tcx > ) -> ValueRef {
223
174
if get_defined_value ( ccx, name) . is_some ( ) {
224
175
ccx. sess ( ) . fatal ( & format ! ( "symbol `{}` already defined" , name) )
225
176
} else {
226
- declare_internal_rust_fn ( ccx, name, fn_type)
177
+ let llfn = declare_fn ( ccx, name, fn_type) ;
178
+ llvm:: SetLinkage ( llfn, llvm:: InternalLinkage ) ;
179
+ llfn
227
180
}
228
181
}
229
182
0 commit comments