1
1
// Translates individual functions in the completed AST to the LLVM IR, using
2
2
// destination-passing style.
3
3
4
- import syntax:: ast;
4
+ import back:: abi;
5
+ import lib:: llvm:: llvm;
6
+ import llvm:: TypeRef ;
7
+ import llvm:: ValueRef ;
5
8
import middle:: trans;
6
9
import middle:: ty;
10
+ import syntax:: ast;
7
11
import trans:: block_ctxt;
8
12
import trans:: crate_ctxt;
9
13
import trans:: fn_ctxt;
10
14
import trans:: local_ctxt;
11
- import lib :: llvm :: llvm :: TypeRef ;
12
- import lib :: llvm :: llvm :: ValueRef ;
15
+
16
+ import std :: ivec ;
13
17
import std:: option:: none;
14
18
import std:: option:: some;
19
+ import std:: str;
15
20
21
+ import LLFalse = lib:: llvm:: False ;
22
+ import LLTrue = lib:: llvm:: True ;
23
+ import lltype_of = trans:: val_ty;
24
+ import option = std:: option:: t;
25
+ import tc = trans_common;
16
26
import type_of_node = trans:: node_id_type;
17
27
18
28
@@ -52,6 +62,13 @@ fn dest_tmp(&@block_ctxt bcx, ty::t t) -> tup(@block_ctxt, dest) {
52
62
ret tup( r. bcx , dest_move ( bcx_tcx ( bcx) , r. val , t) ) ;
53
63
}
54
64
65
+ fn dest_ptr ( & dest dest) -> ValueRef {
66
+ alt ( dest. slot ) {
67
+ dst_nil { tc : : C_null ( tc:: T_ptr ( tc:: T_i8 ( ) ) ) }
68
+ dst_val( ?llptr) { llptr }
69
+ }
70
+ }
71
+
55
72
56
73
// Accessors
57
74
// TODO: When we have overloading, simplify these names!
@@ -64,19 +81,94 @@ fn bcx_fcx(&@block_ctxt bcx) -> @fn_ctxt { ret bcx.fcx; }
64
81
65
82
// Common operations
66
83
67
- fn store ( & @block_ctxt bcx , & dest dest, ValueRef llsrc) -> @block_ctxt {
84
+ // If "cast" is true, casts dest appropriately before the store.
85
+ fn store ( & @block_ctxt bcx , & dest dest, ValueRef llsrc, bool cast)
86
+ -> @block_ctxt {
68
87
alt ( dest. slot ) {
69
88
dst_nil { /* no-op */ }
70
- dst_val( ?lldest) { bcx. build . Store ( llsrc, lldest) ; }
89
+ dst_val( ?lldestptr_orig) {
90
+ auto lldestptr = lldestptr_orig;
91
+ if ( cast) {
92
+ lldestptr = bcx. build . PointerCast ( lldestptr,
93
+ tc:: T_ptr ( lltype_of ( llsrc) ) ) ;
94
+ }
95
+
96
+ bcx. build . Store ( llsrc, lldestptr) ;
97
+ }
98
+ }
99
+ ret bcx;
100
+ }
101
+
102
+ tag heap { hp_task; hp_shared; }
103
+
104
+ // Allocates a value of the given LLVM size on either the task heap or the
105
+ // shared heap.
106
+ fn malloc ( & @block_ctxt bcx , ValueRef lldest, heap heap,
107
+ option[ ValueRef ] llcustom_size_opt ) -> @block_ctxt {
108
+ auto llptrty = llelement_type ( lltype_of ( lldest) ) ;
109
+ auto llty = llelement_type ( llptrty) ;
110
+
111
+ auto lltydescptr = tc:: C_null ( tc:: T_ptr ( bcx_ccx ( bcx) . tydesc_type ) ) ;
112
+
113
+ auto llsize;
114
+ alt ( llcustom_size_opt) {
115
+ none { llsize = trans:: llsize_of ( llty) ; }
116
+ some ( ?llcustom_size) { llsize = llcustom_size; }
117
+ }
118
+
119
+ auto llupcall;
120
+ alt ( heap) {
121
+ hp_task { llupcall = bcx_ccx ( bcx) . upcalls . malloc ; }
122
+ hp_shared { llupcall = bcx_ccx ( bcx) . upcalls . shared_malloc ; }
71
123
}
124
+
125
+ auto llresult = bcx. build . Call ( llupcall, ~[ bcx_fcx ( bcx) . lltaskptr , llsize,
126
+ lltydescptr] ) ;
127
+ llresult = bcx. build . PointerCast ( llresult, llptrty) ;
128
+ bcx. build . Store ( llresult, lldest) ;
72
129
ret bcx;
73
130
}
74
131
75
132
76
133
// AST substructure translation, with destinations
77
134
135
+ fn trans_lit ( & @block_ctxt cx , & dest dest, & ast:: lit lit) -> @block_ctxt {
136
+ auto bcx = cx;
137
+ alt ( lit. node ) {
138
+ ast:: lit_str ( ?s, ast:: sk_unique) {
139
+ auto r = trans_lit_str_common ( bcx_ccx ( bcx) , s) ;
140
+ auto llstackpart = r. _0 ; auto llheappartopt = r. _1 ;
141
+ bcx = store ( bcx, dest, llstackpart, true ) ;
142
+ alt ( llheappartopt) {
143
+ none { /* no-op */ }
144
+ some( ?llheappart) {
145
+ auto lldestptrptr =
146
+ bcx. build . InBoundsGEP ( dest_ptr ( dest) ,
147
+ ~[ tc:: C_int ( 0 ) ,
148
+ tc:: C_uint ( abi:: ivec_elt_elems) ] ) ;
149
+ auto llheappartty = lltype_of ( llheappart) ;
150
+ lldestptrptr =
151
+ bcx. build . PointerCast ( lldestptrptr,
152
+ tc:: T_ptr ( tc:: T_ptr ( llheappartty) ) ) ;
153
+ malloc ( bcx, lldestptrptr, hp_shared, none) ;
154
+ auto lldestptr = bcx. build . Load ( lldestptrptr) ;
155
+ bcx. build . Store ( llheappart, lldestptr) ;
156
+ }
157
+ }
158
+ }
159
+ _ {
160
+ bcx = store ( bcx, dest, trans_lit_common ( bcx_ccx ( bcx) , lit) , false ) ;
161
+ }
162
+ }
163
+
164
+ ret bcx;
165
+ }
166
+
78
167
fn trans_expr ( & @block_ctxt bcx , & dest dest, & @ast:: expr expr) -> @block_ctxt {
79
- ret bcx; // TODO
168
+ alt ( expr. node ) {
169
+ ast:: expr_lit ( ?lit) { trans_lit ( bcx, dest, * lit) ; ret bcx; }
170
+ _ { fail "unhandled expr type in trans_expr" ; }
171
+ }
80
172
}
81
173
82
174
fn trans_recv ( & @block_ctxt bcx , & dest dest, & @ast:: expr expr) -> @block_ctxt {
@@ -105,8 +197,83 @@ fn trans_block(&@block_ctxt cx, &dest dest, &ast::block block)
105
197
}
106
198
107
199
200
+
108
201
// AST substructure translation, without destinations
109
202
203
+ // Common setup code shared between the crate-constant literal string case and
204
+ // the block-local literal string case. We don't use destination-passing style
205
+ // since that doesn't work for crate constants.
206
+ fn trans_lit_str_common ( & @crate_ctxt ccx , & str s)
207
+ -> tup ( ValueRef , option[ ValueRef ] ) {
208
+ auto len = str:: byte_len ( s) ;
209
+
210
+ auto array = ~[ ] ;
211
+ for ( u8 ch in s) { array += ~[ tc:: C_u8 ( ch as uint ) ] ; }
212
+ array += ~[ tc:: C_u8 ( 0 u) ] ;
213
+
214
+ if len < abi:: ivec_default_length - 1 u { // minus 1 because of the \0
215
+ while ( ivec:: len ( array) < abi:: ivec_default_length) {
216
+ array += ~[ tc:: C_u8 ( 0 u) ] ;
217
+ }
218
+
219
+ ret tup( tc:: C_struct ( ~[ tc:: C_uint ( len + 1 u) ,
220
+ tc:: C_uint ( abi:: ivec_default_length) ,
221
+ tc:: C_array ( tc:: T_i8 ( ) , array) ] ) ,
222
+ none) ;
223
+ }
224
+
225
+ auto llarray = tc:: C_array ( tc:: T_i8 ( ) , array) ;
226
+ ret tup( tc:: C_struct ( ~[ tc:: C_uint ( 0 u) ,
227
+ tc:: C_uint ( abi:: ivec_default_length) ,
228
+ tc:: C_null ( tc:: T_ptr ( lltype_of ( llarray) ) ) ] ) ,
229
+ some ( llarray) ) ;
230
+ }
231
+
232
+ // As above, we don't use destination-passing style here.
233
+ fn trans_lit_common ( & @crate_ctxt ccx , & ast:: lit lit) -> ValueRef {
234
+ alt ( lit. node ) {
235
+ ast:: lit_int ( ?i) { ret tc:: C_int ( i) ; }
236
+ ast:: lit_uint ( ?u) { ret tc:: C_int ( u as int ) ; }
237
+ ast:: lit_mach_int ( ?tm, ?i) {
238
+ // FIXME: the entire handling of mach types falls apart
239
+ // if target int width is larger than host, at the moment;
240
+ // re-do the mach-int types using 'big' when that works.
241
+
242
+ auto t = tc:: T_int ( ) ;
243
+ auto s = LLTrue ;
244
+ alt ( tm) {
245
+ ast:: ty_u8 { t = tc:: T_i8 ( ) ; s = LLFalse ; }
246
+ ast:: ty_u16 { t = tc:: T_i16 ( ) ; s = LLFalse ; }
247
+ ast:: ty_u32 { t = tc:: T_i32 ( ) ; s = LLFalse ; }
248
+ ast:: ty_u64 { t = tc:: T_i64 ( ) ; s = LLFalse ; }
249
+ ast:: ty_i8 { t = tc:: T_i8 ( ) ; }
250
+ ast:: ty_i16 { t = tc:: T_i16 ( ) ; }
251
+ ast:: ty_i32 { t = tc:: T_i32 ( ) ; }
252
+ ast:: ty_i64 { t = tc:: T_i64 ( ) ; }
253
+ }
254
+ ret tc:: C_integral ( t, i as uint , s) ;
255
+ }
256
+ ast:: lit_float ( ?fs) { ret tc:: C_float ( fs) ; }
257
+ ast:: lit_mach_float ( ?tm, ?s) {
258
+ auto t = tc:: T_float ( ) ;
259
+ alt ( tm) {
260
+ ast:: ty_f32 { t = tc:: T_f32 ( ) ; }
261
+ ast:: ty_f64 { t = tc:: T_f64 ( ) ; }
262
+ }
263
+ ret tc:: C_floating ( s, t) ;
264
+ }
265
+ ast:: lit_char ( ?c) {
266
+ ret tc:: C_integral ( tc:: T_char ( ) , c as uint , LLFalse ) ;
267
+ }
268
+ ast:: lit_bool ( ?b) { ret tc:: C_bool ( b) ; }
269
+ ast:: lit_nil { ret tc:: C_nil ( ) ; }
270
+ ast:: lit_str ( ?s, ast:: sk_rc) { ret tc:: C_str ( ccx, s) ; }
271
+ ast:: lit_str ( ?s, ast:: sk_unique) {
272
+ fail "unique str in trans_lit_common" ;
273
+ }
274
+ }
275
+ }
276
+
110
277
fn trans_init_local ( & @block_ctxt bcx , & @ast:: local local) -> @block_ctxt {
111
278
auto llptr = bcx_fcx ( bcx) . lllocals . get ( local. node . id ) ;
112
279
@@ -129,7 +296,7 @@ fn trans_init_local(&@block_ctxt bcx, &@ast::local local) -> @block_ctxt {
129
296
}
130
297
none {
131
298
ret store( bcx, dest_copy ( bcx_tcx ( bcx) , llptr, t) ,
132
- trans_common :: C_null ( llelement_type ( trans:: val_ty ( llptr) ) ) ) ;
299
+ tc :: C_null ( llelement_type ( trans:: val_ty ( llptr) ) ) , false ) ;
133
300
}
134
301
}
135
302
}
0 commit comments