2
2
// destination-passing style.
3
3
4
4
import back:: abi;
5
+ import back:: link;
5
6
import lib:: llvm:: llvm;
6
7
import llvm:: TypeRef ;
7
8
import llvm:: ValueRef ;
8
9
import middle:: trans;
9
10
import middle:: ty;
10
11
import syntax:: ast;
12
+ import syntax:: codemap:: span;
11
13
import trans:: block_ctxt;
12
14
import trans:: crate_ctxt;
13
15
import trans:: fn_ctxt;
14
16
import trans:: local_ctxt;
17
+ import util:: ppaux;
15
18
16
19
import std:: ivec;
17
20
import std:: option:: none;
@@ -20,6 +23,7 @@ import std::str;
20
23
21
24
import LLFalse = lib:: llvm:: False ;
22
25
import LLTrue = lib:: llvm:: True ;
26
+ import ll = lib:: llvm;
23
27
import lltype_of = trans:: val_ty;
24
28
import option = std:: option:: t;
25
29
import tc = trans_common;
@@ -40,26 +44,35 @@ tag dest_slot {
40
44
dst_val ( ValueRef ) ;
41
45
}
42
46
43
- type dest = rec ( dest_slot slot, bool move) ;
47
+ tag dest_mode { dm_copy; dm_move; dm_alias; }
48
+
49
+ type dest = rec ( dest_slot slot, dest_mode mode) ;
44
50
45
51
fn dest_slot_for_ptr ( & ty:: ctxt tcx, ValueRef llptr, ty:: t t) -> dest_slot {
46
52
if ty:: type_is_nil ( tcx, t) { dst_nil } else { dst_val ( llptr) }
47
53
}
48
54
49
55
fn dest_copy ( & ty:: ctxt tcx, ValueRef llptr, ty:: t t) -> dest {
50
- ret rec ( slot=dest_slot_for_ptr ( tcx, llptr, t) , move = false ) ;
56
+ ret rec ( slot=dest_slot_for_ptr ( tcx, llptr, t) , mode=dm_copy ) ;
51
57
}
52
58
53
59
fn dest_move ( & ty:: ctxt tcx, ValueRef llptr, ty:: t t) -> dest {
54
- ret rec ( slot=dest_slot_for_ptr ( tcx, llptr, t) , move =true ) ;
60
+ ret rec ( slot=dest_slot_for_ptr ( tcx, llptr, t) , mode=dm_move) ;
61
+ }
62
+
63
+ fn dest_alias ( & ty:: ctxt tcx, ValueRef llptr, ty:: t t) -> dest {
64
+ ret rec ( slot=dest_slot_for_ptr ( tcx, llptr, t) , mode=dm_alias) ;
55
65
}
56
66
57
- fn dest_tmp ( & @block_ctxt bcx , ty:: t t) -> tup ( @block_ctxt , dest ) {
67
+ fn dest_tmp ( & @block_ctxt bcx , ty:: t t, bool alias ) -> tup ( @block_ctxt , dest ) {
68
+ auto mode = if alias { dm_alias } else { dm_move } ;
58
69
if ty:: type_is_nil ( bcx_tcx ( bcx) , t) {
59
- ret tup ( bcx, rec ( slot=dst_nil, move = true ) ) ;
70
+ ret tup ( bcx, rec ( slot=dst_nil, mode=mode ) ) ;
60
71
}
61
72
auto r = trans:: alloc_ty ( bcx, t) ;
62
- ret tup( r. bcx , dest_move ( bcx_tcx ( bcx) , r. val , t) ) ;
73
+ trans:: add_clean ( bcx, r. val , t) ;
74
+ ret tup ( r. bcx , rec ( slot=dest_slot_for_ptr ( bcx_tcx ( bcx) , r. val , t) ,
75
+ mode=mode) ) ;
63
76
}
64
77
65
78
fn dest_ptr ( & dest dest) -> ValueRef {
@@ -77,6 +90,7 @@ fn bcx_tcx(&@block_ctxt bcx) -> ty::ctxt { ret bcx.fcx.lcx.ccx.tcx; }
77
90
fn bcx_ccx ( & @block_ctxt bcx ) -> @crate_ctxt { ret bcx. fcx . lcx . ccx ; }
78
91
fn bcx_lcx ( & @block_ctxt bcx ) -> @local_ctxt { ret bcx. fcx . lcx ; }
79
92
fn bcx_fcx ( & @block_ctxt bcx ) -> @fn_ctxt { ret bcx. fcx ; }
93
+ fn lcx_ccx ( & @local_ctxt lcx ) -> @crate_ctxt { ret lcx. ccx ; }
80
94
81
95
82
96
// Common operations
@@ -164,9 +178,92 @@ fn trans_lit(&@block_ctxt cx, &dest dest, &ast::lit lit) -> @block_ctxt {
164
178
ret bcx;
165
179
}
166
180
181
+ fn trans_log ( & @block_ctxt cx , & span sp, int level , & @ast:: expr expr)
182
+ -> @block_ctxt {
183
+ fn trans_log_level ( & @local_ctxt lcx ) -> ValueRef {
184
+ auto modname = str:: connect_ivec ( lcx. module_path , "::" ) ;
185
+
186
+ if ( lcx_ccx ( lcx) . module_data . contains_key ( modname) ) {
187
+ ret lcx_ccx ( lcx) . module_data . get ( modname) ;
188
+ }
189
+
190
+ auto s =
191
+ link:: mangle_internal_name_by_path_and_seq ( lcx_ccx ( lcx) ,
192
+ lcx. module_path ,
193
+ "loglevel" ) ;
194
+ auto lllevelptr = llvm:: LLVMAddGlobal ( lcx. ccx . llmod , tc:: T_int ( ) ,
195
+ str:: buf ( s) ) ;
196
+ llvm:: LLVMSetGlobalConstant ( lllevelptr, LLFalse ) ;
197
+ llvm:: LLVMSetInitializer ( lllevelptr, tc:: C_int ( 0 ) ) ;
198
+ llvm:: LLVMSetLinkage ( lllevelptr, lib:: llvm:: LLVMInternalLinkage as
199
+ llvm:: Linkage ) ;
200
+ lcx_ccx ( lcx) . module_data . insert ( modname, lllevelptr) ;
201
+ ret lllevelptr;
202
+ }
203
+
204
+ fn trans_log_upcall ( & @block_ctxt bcx , & span sp, ValueRef in_llval,
205
+ int level , ty:: t t) {
206
+ auto llval = in_llval;
207
+ auto by_val; auto llupcall;
208
+ alt ( ty:: struct ( bcx_tcx ( bcx) , t) ) {
209
+ ty:: ty_machine ( ast:: ty_f32) {
210
+ by_val = true ; llupcall = bcx_ccx ( bcx) . upcalls . log_float ;
211
+ }
212
+ ty:: ty_machine ( ast:: ty_f64) | ty:: ty_float {
213
+ by_val = false ; llupcall = bcx_ccx ( bcx) . upcalls . log_double ;
214
+ }
215
+ ty:: ty_bool | ty:: ty_machine ( ast:: ty_i8) |
216
+ ty:: ty_machine ( ast:: ty_i16) | ty:: ty_machine ( ast:: ty_u8) |
217
+ ty:: ty_machine ( ast:: ty_u16) {
218
+ by_val = true ; llupcall = bcx_ccx ( bcx) . upcalls . log_int ;
219
+ llval = bcx. build . ZExt ( llval, tc:: T_i32 ( ) ) ;
220
+ }
221
+ ty:: ty_int | ty:: ty_machine ( ast:: ty_i32) |
222
+ ty:: ty_machine ( ast:: ty_u32) {
223
+ by_val = true ; llupcall = bcx_ccx ( bcx) . upcalls . log_int ;
224
+ }
225
+ _ {
226
+ bcx_ccx( bcx) . sess . span_unimpl ( sp, "logging for values of type " +
227
+ ppaux:: ty_to_str ( bcx_tcx ( bcx) , t) ) ;
228
+ }
229
+ }
230
+
231
+ if by_val { llval = bcx. build . Load ( llval) ; }
232
+ bcx. build . Call ( llupcall,
233
+ ~[ bcx_fcx ( bcx) . lltaskptr , tc:: C_int ( level) , llval] ) ;
234
+ }
235
+
236
+ auto bcx = cx;
237
+
238
+ auto lllevelptr = trans_log_level ( bcx_lcx ( bcx) ) ;
239
+
240
+ auto log_bcx = trans:: new_scope_block_ctxt ( bcx, "log" ) ;
241
+ auto next_bcx = trans:: new_scope_block_ctxt ( bcx, "next_log" ) ;
242
+
243
+ auto should_log = bcx. build . ICmp ( ll:: LLVMIntSGE ,
244
+ bcx. build . Load ( lllevelptr) ,
245
+ tc:: C_int ( level) ) ;
246
+ bcx. build . CondBr ( should_log, log_bcx. llbb , next_bcx. llbb ) ;
247
+
248
+ auto expr_t = ty:: expr_ty ( bcx_tcx ( log_bcx) , expr) ;
249
+ auto r = dest_tmp ( log_bcx, expr_t, true ) ;
250
+ log_bcx = r. _0 ; auto tmp = r. _1 ;
251
+ log_bcx = trans_expr ( log_bcx, tmp, expr) ;
252
+
253
+ trans_log_upcall ( log_bcx, sp, dest_ptr ( tmp) , level, expr_t) ;
254
+
255
+ log_bcx = trans:: trans_block_cleanups ( log_bcx,
256
+ trans:: find_scope_cx ( log_bcx) ) ;
257
+ log_bcx. build . Br ( next_bcx. llbb ) ;
258
+ ret next_bcx;
259
+ }
260
+
167
261
fn trans_expr ( & @block_ctxt bcx , & dest dest, & @ast:: expr expr) -> @block_ctxt {
168
262
alt ( expr. node ) {
169
263
ast:: expr_lit ( ?lit) { trans_lit ( bcx, dest, * lit) ; ret bcx; }
264
+ ast:: expr_log ( ?level, ?operand) {
265
+ ret trans_log ( bcx, expr. span , level, operand) ;
266
+ }
170
267
_ { fail "unhandled expr type in trans_expr" ; }
171
268
}
172
269
}
@@ -191,9 +288,12 @@ fn trans_block(&@block_ctxt cx, &dest dest, &ast::block block)
191
288
}
192
289
193
290
alt ( block. node . expr ) {
194
- some ( ?e) { ret trans_expr ( bcx, dest, e) ; }
195
- none { ret bcx ; }
291
+ some ( ?e) { bcx = trans_expr ( bcx, dest, e) ; }
292
+ none { /* no-op */ }
196
293
}
294
+
295
+ bcx = trans:: trans_block_cleanups ( bcx, trans:: find_scope_cx ( bcx) ) ;
296
+ ret bcx;
197
297
}
198
298
199
299
@@ -305,7 +405,7 @@ fn trans_stmt(&@block_ctxt cx, &@ast::stmt stmt) -> @block_ctxt {
305
405
auto bcx = cx;
306
406
alt ( stmt. node ) {
307
407
ast:: stmt_expr ( ?e, _) {
308
- auto tmp_r = dest_tmp ( bcx, ty:: expr_ty ( bcx_tcx ( bcx) , e) ) ;
408
+ auto tmp_r = dest_tmp ( bcx, ty:: expr_ty ( bcx_tcx ( bcx) , e) , true ) ;
309
409
bcx = tmp_r. _0 ; auto tmp = tmp_r. _1 ;
310
410
ret trans_expr ( bcx, tmp, e) ;
311
411
}
0 commit comments