To protect your data, the CISO officer has suggested users to enable GitLab 2FA as soon as possible.

muirbuilder.rs 68 KB
Newer Older
1
use super::common::*;
2
use ast::op::*;
Kunshan Wang's avatar
Kunshan Wang committed
3
use ast::inst::*;
4
use std;
5

6
pub struct MuIRBuilder {
7
    /// ref to MuVM
8
    mvm: *const MuVM,
9
10
11
12
13
14
15
16
17
18
19
20

    /// Point to the C-visible CMuIRBuilder so that `load` and `abort` can deallocate itself.
    pub c_struct: *mut CMuIRBuilder,

    /// Map IDs to names. Items are inserted during `gen_sym`. MuIRBuilder is supposed to be used
    /// by one thread, so there is no need for locking.
    id_name_map: HashMap<MuID, MuName>,

    /// The "trantient bundle" includes everything being built here.
    bundle: TrantientBundle,
}

21
pub type IdBMap<T> = HashMap<MuID, Box<T>>;
22
23
24
25

/// A trantient bundle, i.e. the bundle being built, but not yet loaded into the MuVM.
#[derive(Default)]
pub struct TrantientBundle {
26
27
28
29
30
31
32
33
34
35
36
37
    types: IdBMap<NodeType>,
    sigs: IdBMap<NodeFuncSig>,
    consts: IdBMap<NodeConst>,
    globals: IdBMap<NodeGlobalCell>,
    funcs: IdBMap<NodeFunc>,
    expfuncs: IdBMap<NodeExpFunc>,
    funcvers: IdBMap<NodeFuncVer>,
    bbs: IdBMap<NodeBB>,
    insts: IdBMap<NodeInst>,
    dest_clauses: IdBMap<NodeDestClause>,
    exc_clauses: IdBMap<NodeExcClause>,
    ka_clauses: IdBMap<NodeKeepaliveClause>,
38
39
}

40
41
impl MuIRBuilder {
    pub fn new(mvm: *const MuVM) -> Box<MuIRBuilder> {
42
43
44
45
46
47
48
        Box::new(MuIRBuilder {
            mvm: mvm,
            c_struct: ptr::null_mut(),
            id_name_map: Default::default(),
            bundle: Default::default(),
        })
    }
49

50
    #[inline(always)]
51
52
53
    fn get_mvm<'a, 'b>(&'a mut self) -> &'b MuVM {
        //self.mvm
        unsafe { & *self.mvm }
54
55
56
    }

    #[inline(always)]
57
    fn get_vm<'a, 'b>(&'a mut self) -> &'b VM {
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
        &self.get_mvm().vm
    }

    #[inline(always)]
    fn next_id(&mut self) -> MuID {
        self.get_vm().next_id()
    }

    fn deallocate(&mut self) {
        let c_struct = self.c_struct;
        let b_ptr = self as *mut MuIRBuilder;
        debug!("Deallocating MuIRBuilder {:?} and CMuIRBuilder {:?}...", b_ptr, c_struct);
        unsafe {
            Box::from_raw(c_struct);
            Box::from_raw(b_ptr);
        }
    }

    /// Get the Mu name of the `id`. This will consume the entry in the `id_name_map`. For this
    /// reason, this function is only called when the actual MuEntity that has this ID is created
    /// (such as `new_type_int`).
    fn consume_name_of(&mut self, id: MuID) -> Option<MuName> {
        self.id_name_map.remove(&id)
    }

    pub fn load(&mut self) {
        load_bundle(self);
        self.deallocate();
    }

    pub fn abort(&mut self) {
        info!("Aborting boot image building...");
        self.deallocate();
    }

    pub fn gen_sym(&mut self, name: Option<String>) -> MuID {
        let my_id = self.next_id();

        debug!("gen_sym({:?}) -> {}", name, my_id);

        match name {
            None => {},
            Some(the_name) => {
                let old = self.id_name_map.insert(my_id, the_name);
                debug_assert!(old.is_none(), "ID already exists: {}, new name: {}, old name: {}",
                my_id, self.id_name_map.get(&my_id).unwrap(), old.unwrap());
            },
        };

        my_id
    }

    pub fn new_type_int(&mut self, id: MuID, len: c_int) {
        self.bundle.types.insert(id, Box::new(NodeType::TypeInt { id: id, len: len }));
    }

    pub fn new_type_float(&mut self, id: MuID) {
115
        self.bundle.types.insert(id, Box::new(NodeType::TypeFloat { id: id }));
116
117
118
    }

    pub fn new_type_double(&mut self, id: MuID) {
119
        self.bundle.types.insert(id, Box::new(NodeType::TypeDouble { id: id }));
120
121
122
123
124
125
126
127
    }

    pub fn new_type_uptr(&mut self, id: MuID, ty: MuID) {
        self.bundle.types.insert(id, Box::new(NodeType::TypeUPtr{ id: id,
            ty: ty }));
    }

    pub fn new_type_ufuncptr(&mut self, id: MuID, sig: MuID) {
Kunshan Wang's avatar
Kunshan Wang committed
128
129
        self.bundle.types.insert(id, Box::new(NodeType::TypeUFuncPtr{ id: id,
            sig: sig }));
130
131
132
133
134
135
136
137
    }

    pub fn new_type_struct(&mut self, id: MuID, fieldtys: Vec<MuID>) {
        self.bundle.types.insert(id, Box::new(NodeType::TypeStruct { id: id,
            fieldtys: fieldtys }));
    }

    pub fn new_type_hybrid(&mut self, id: MuID, fixedtys: Vec<MuID>, varty: MuID) {
138
139
        self.bundle.types.insert(id, Box::new(NodeType::TypeHybrid { id: id,
            fixedtys: fixedtys, varty: varty }));
140
141
142
    }

    pub fn new_type_array(&mut self, id: MuID, elemty: MuID, len: u64) {
143
144
        self.bundle.types.insert(id, Box::new(NodeType::TypeArray { id: id,
            elemty: elemty, len: len as usize }));
145
146
147
    }

    pub fn new_type_vector(&mut self, id: MuID, elemty: MuID, len: u64) {
148
149
        self.bundle.types.insert(id, Box::new(NodeType::TypeVector { id: id,
            elemty: elemty, len: len as usize }));
150
151
152
    }

    pub fn new_type_void(&mut self, id: MuID) {
153
        self.bundle.types.insert(id, Box::new(NodeType::TypeVoid { id: id }));
154
155
156
    }

    pub fn new_type_ref(&mut self, id: MuID, ty: MuID) {
157
158
        self.bundle.types.insert(id, Box::new(NodeType::TypeRef{ id: id,
            ty: ty }));
159
160
161
    }

    pub fn new_type_iref(&mut self, id: MuID, ty: MuID) {
162
163
        self.bundle.types.insert(id, Box::new(NodeType::TypeIRef{ id: id,
            ty: ty }));
164
165
166
    }

    pub fn new_type_weakref(&mut self, id: MuID, ty: MuID) {
167
168
        self.bundle.types.insert(id, Box::new(NodeType::TypeWeakRef{ id: id,
            ty: ty }));
169
170
171
    }

    pub fn new_type_funcref(&mut self, id: MuID, sig: MuID) {
172
173
        self.bundle.types.insert(id, Box::new(NodeType::TypeFuncRef{ id: id,
            sig: sig }));
174
175
176
    }

    pub fn new_type_tagref64(&mut self, id: MuID) {
177
        self.bundle.types.insert(id, Box::new(NodeType::TypeTagRef64 { id: id }));
178
179
180
    }

    pub fn new_type_threadref(&mut self, id: MuID) {
181
        self.bundle.types.insert(id, Box::new(NodeType::TypeThreadRef { id: id }));
182
183
184
    }

    pub fn new_type_stackref(&mut self, id: MuID) {
185
        self.bundle.types.insert(id, Box::new(NodeType::TypeStackRef { id: id }));
186
187
188
    }

    pub fn new_type_framecursorref(&mut self, id: MuID) {
189
        self.bundle.types.insert(id, Box::new(NodeType::TypeFrameCursorRef { id: id }));
190
191
192
    }

    pub fn new_type_irbuilderref(&mut self, id: MuID) {
193
        self.bundle.types.insert(id, Box::new(NodeType::TypeIRBuilderRef { id: id }));
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
    }

    pub fn new_funcsig(&mut self, id: MuID, paramtys: Vec<MuID>, rettys: Vec<MuID>) {
        self.bundle.sigs.insert(id, Box::new(NodeFuncSig { id: id,
            paramtys: paramtys, rettys: rettys }));
    }

    pub fn new_const_int(&mut self, id: MuID, ty: MuID, value: u64) {
        self.bundle.consts.insert(id, Box::new(NodeConst::ConstInt { id: id,
            ty: ty, value: value }));
    }

    pub fn new_const_int_ex(&mut self, id: MuID, ty: MuID, values: &[u64]) {
        panic!("Not implemented")
    }

    pub fn new_const_float(&mut self, id: MuID, ty: MuID, value: f32) {
211
212
        self.bundle.consts.insert(id, Box::new(NodeConst::ConstFloat { id: id,
            ty: ty, value: value }));
213
214
215
    }

    pub fn new_const_double(&mut self, id: MuID, ty: MuID, value: f64) {
216
217
        self.bundle.consts.insert(id, Box::new(NodeConst::ConstDouble { id: id,
            ty: ty, value: value }));
218
219
220
    }

    pub fn new_const_null(&mut self, id: MuID, ty: MuID) {
221
222
        self.bundle.consts.insert(id, Box::new(NodeConst::ConstNull { id: id,
            ty: ty }));
223
224
225
    }

    pub fn new_const_seq(&mut self, id: MuID, ty: MuID, elems: Vec<MuID>) {
226
227
        self.bundle.consts.insert(id, Box::new(NodeConst::ConstSeq { id: id,
            ty: ty, elems: elems }));
228
229
230
    }

    pub fn new_const_extern(&mut self, id: MuID, ty: MuID, symbol: String) {
231
232
        self.bundle.consts.insert(id, Box::new(NodeConst::ConstExtern { id: id,
            ty: ty, symbol: symbol }));
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
    }

    pub fn new_global_cell(&mut self, id: MuID, ty: MuID) {
        self.bundle.globals.insert(id, Box::new(NodeGlobalCell { id: id,
            ty: ty }));
    }

    pub fn new_func(&mut self, id: MuID, sig: MuID) {
        self.bundle.funcs.insert(id, Box::new(NodeFunc { id: id,
            sig: sig }));
    }

    pub fn new_exp_func(&mut self, id: MuID, func: MuID, callconv: CMuCallConv, cookie: MuID) {
        panic!("Not implemented")
    }

    pub fn new_func_ver(&mut self, id: MuID, func: MuID, bbs: Vec<MuID>) {
        self.bundle.funcvers.insert(id, Box::new(NodeFuncVer { id: id,
            func: func, bbs: bbs }));
    }

    pub fn new_bb(&mut self, id: MuID, nor_param_ids: Vec<MuID>, nor_param_types: Vec<MuID>, exc_param_id: Option<MuID>, insts: Vec<MuID>) {
        self.bundle.bbs.insert(id, Box::new(NodeBB { id: id,
256
257
            nor_param_ids: nor_param_ids, nor_param_types: nor_param_types,
            exc_param_id: exc_param_id, insts: insts }));
258
259
260
    }

    pub fn new_dest_clause(&mut self, id: MuID, dest: MuID, vars: Vec<MuID>) {
261
262
        self.bundle.dest_clauses.insert(id, Box::new(NodeDestClause { id: id,
            dest: dest, vars: vars }));
263
264
265
    }

    pub fn new_exc_clause(&mut self, id: MuID, nor: MuID, exc: MuID) {
266
267
        self.bundle.exc_clauses.insert(id, Box::new(NodeExcClause { id: id,
            nor: nor, exc: exc }));
268
269
270
    }

    pub fn new_keepalive_clause(&mut self, id: MuID, vars: Vec<MuID>) {
271
272
        self.bundle.ka_clauses.insert(id, Box::new(NodeKeepaliveClause { id: id,
            vars: vars }));
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
    }

    pub fn new_csc_ret_with(&mut self, id: MuID, rettys: Vec<MuID>) {
        panic!("Not implemented")
    }

    pub fn new_csc_kill_old(&mut self, id: MuID) {
        panic!("Not implemented")
    }

    pub fn new_nsc_pass_values(&mut self, id: MuID, tys: Vec<MuID>, vars: Vec<MuID>) {
        panic!("Not implemented")
    }

    pub fn new_nsc_throw_exc(&mut self, id: MuID, exc: MuID) {
        panic!("Not implemented")
    }

291
292
293
294
295
    #[inline(always)]
    fn add_inst(&mut self, id: MuID, inst: NodeInst) {
        self.bundle.insts.insert(id, Box::new(inst));
    }

296
    pub fn new_binop(&mut self, id: MuID, result_id: MuID, optr: CMuBinOptr, ty: MuID, opnd1: MuID, opnd2: MuID, exc_clause: Option<MuID>) {
297
298
        self.add_inst(id, NodeInst::NodeBinOp {
            id: id, result_id: result_id, status_result_ids: vec![],
299
            optr: optr, flags: 0, ty: ty, opnd1: opnd1, opnd2: opnd2,
300
301
            exc_clause: exc_clause
        });
302
303
304
305
306
307
308
    }

    pub fn new_binop_with_status(&mut self, id: MuID, result_id: MuID, status_result_ids: Vec<MuID>, optr: CMuBinOptr, status_flags: CMuBinOpStatus, ty: MuID, opnd1: MuID, opnd2: MuID, exc_clause: Option<MuID>) {
        panic!("Not implemented")
    }

    pub fn new_cmp(&mut self, id: MuID, result_id: MuID, optr: CMuCmpOptr, ty: MuID, opnd1: MuID, opnd2: MuID) {
309
310
311
312
        self.add_inst(id, NodeInst::NodeCmp {
            id: id, result_id: result_id,
            optr: optr, ty: ty, opnd1: opnd1, opnd2: opnd2
        });
313
314
315
    }

    pub fn new_conv(&mut self, id: MuID, result_id: MuID, optr: CMuConvOptr, from_ty: MuID, to_ty: MuID, opnd: MuID) {
316
317
318
319
        self.add_inst(id, NodeInst::NodeConv {
            id: id, result_id: result_id,
            optr: optr, from_ty: from_ty, to_ty: to_ty, opnd: opnd
        });
320
321
322
    }

    pub fn new_select(&mut self, id: MuID, result_id: MuID, cond_ty: MuID, opnd_ty: MuID, cond: MuID, if_true: MuID, if_false: MuID) {
323
324
325
326
327
        self.add_inst(id, NodeInst::NodeSelect {
            id: id, result_id: result_id,
            cond_ty: cond_ty, opnd_ty: opnd_ty, cond: cond,
            if_true: if_true, if_false: if_false
        });
328
329
330
    }

    pub fn new_branch(&mut self, id: MuID, dest: MuID) {
331
332
333
        self.add_inst(id, NodeInst::NodeBranch {
            id: id, dest: dest
        });
334
335
336
    }

    pub fn new_branch2(&mut self, id: MuID, cond: MuID, if_true: MuID, if_false: MuID) {
337
338
339
        self.add_inst(id, NodeInst::NodeBranch2 {
            id: id, cond: cond, if_true: if_true, if_false: if_false
        });
340
341
342
    }

    pub fn new_switch(&mut self, id: MuID, opnd_ty: MuID, opnd: MuID, default_dest: MuID, cases: Vec<MuID>, dests: Vec<MuID>) {
343
344
345
346
        self.add_inst(id, NodeInst::NodeSwitch {
            id: id, opnd_ty: opnd_ty, opnd: opnd, default_dest: default_dest,
            cases: cases, dests: dests
        });
347
348
349
    }

    pub fn new_call(&mut self, id: MuID, result_ids: Vec<MuID>, sig: MuID, callee: MuID, args: Vec<MuID>, exc_clause: Option<MuID>, keepalive_clause: Option<MuID>) {
350
351
352
353
354
        self.add_inst(id, NodeInst::NodeCall {
            id: id, result_ids: result_ids,
            sig: sig, callee: callee, args: args,
            exc_clause: exc_clause, keepalive_clause: keepalive_clause
        });
355
356
357
    }

    pub fn new_tailcall(&mut self, id: MuID, sig: MuID, callee: MuID, args: Vec<MuID>) {
358
359
360
        self.add_inst(id, NodeInst::NodeTailCall {
            id: id, sig: sig, callee: callee, args: args
        });
361
362
363
    }

    pub fn new_ret(&mut self, id: MuID, rvs: Vec<MuID>) {
364
365
366
        self.add_inst(id, NodeInst::NodeRet {
            id: id, rvs: rvs
        });
367
368
369
    }

    pub fn new_throw(&mut self, id: MuID, exc: MuID) {
370
371
372
        self.add_inst(id, NodeInst::NodeThrow {
            id: id, exc: exc
        });
373
374
375
    }

    pub fn new_extractvalue(&mut self, id: MuID, result_id: MuID, strty: MuID, index: c_int, opnd: MuID) {
376
377
378
        self.add_inst(id, NodeInst::NodeExtractValue {
            id: id, result_id: result_id, strty: strty, index: index, opnd: opnd
        });
379
380
381
    }

    pub fn new_insertvalue(&mut self, id: MuID, result_id: MuID, strty: MuID, index: c_int, opnd: MuID, newval: MuID) {
382
383
384
        self.add_inst(id, NodeInst::NodeInsertValue {
            id: id, result_id: result_id, strty: strty, index: index, opnd: opnd, newval: newval
        });
385
386
387
    }

    pub fn new_extractelement(&mut self, id: MuID, result_id: MuID, seqty: MuID, indty: MuID, opnd: MuID, index: MuID) {
388
389
390
        self.add_inst(id, NodeInst::NodeExtractElement {
            id: id, result_id: result_id, seqty: seqty, indty: indty, opnd: opnd, index: index
        });
391
392
393
    }

    pub fn new_insertelement(&mut self, id: MuID, result_id: MuID, seqty: MuID, indty: MuID, opnd: MuID, index: MuID, newval: MuID) {
394
395
396
        self.add_inst(id, NodeInst::NodeInsertElement {
            id: id, result_id: result_id, seqty: seqty, indty: indty, opnd: opnd, index: index, newval: newval
        });
397
398
399
    }

    pub fn new_shufflevector(&mut self, id: MuID, result_id: MuID, vecty: MuID, maskty: MuID, vec1: MuID, vec2: MuID, mask: MuID) {
400
401
402
        self.add_inst(id, NodeInst::NodeShuffleVector {
            id: id, result_id: result_id, vecty: vecty, maskty: maskty, vec1: vec1, vec2: vec2, mask: mask
        });
403
404
405
    }

    pub fn new_new(&mut self, id: MuID, result_id: MuID, allocty: MuID, exc_clause: Option<MuID>) {
406
407
408
        self.add_inst(id, NodeInst::NodeNew {
            id: id, result_id: result_id, allocty: allocty, exc_clause: exc_clause
        });
409
410
411
    }

    pub fn new_newhybrid(&mut self, id: MuID, result_id: MuID, allocty: MuID, lenty: MuID, length: MuID, exc_clause: Option<MuID>) {
412
413
414
        self.add_inst(id, NodeInst::NodeNewHybrid {
            id: id, result_id: result_id, allocty: allocty, lenty: lenty, length: length, exc_clause: exc_clause
        });
415
416
417
    }

    pub fn new_alloca(&mut self, id: MuID, result_id: MuID, allocty: MuID, exc_clause: Option<MuID>) {
418
419
420
        self.add_inst(id, NodeInst::NodeAlloca {
            id: id, result_id: result_id, allocty: allocty, exc_clause: exc_clause
        });
421
422
423
    }

    pub fn new_allocahybrid(&mut self, id: MuID, result_id: MuID, allocty: MuID, lenty: MuID, length: MuID, exc_clause: Option<MuID>) {
424
425
426
        self.add_inst(id, NodeInst::NodeAllocaHybrid {
            id: id, result_id: result_id, allocty: allocty, lenty: lenty, length: length, exc_clause: exc_clause
        });
427
428
429
    }

    pub fn new_getiref(&mut self, id: MuID, result_id: MuID, refty: MuID, opnd: MuID) {
430
431
432
        self.add_inst(id, NodeInst::NodeGetIRef {
            id: id, result_id: result_id, refty: refty, opnd: opnd
        });
433
434
435
    }

    pub fn new_getfieldiref(&mut self, id: MuID, result_id: MuID, is_ptr: bool, refty: MuID, index: c_int, opnd: MuID) {
436
437
438
        self.add_inst(id, NodeInst::NodeGetFieldIRef {
            id: id, result_id: result_id, is_ptr: is_ptr, refty: refty, index: index, opnd: opnd
        });
439
440
441
    }

    pub fn new_getelemiref(&mut self, id: MuID, result_id: MuID, is_ptr: bool, refty: MuID, indty: MuID, opnd: MuID, index: MuID) {
442
443
444
        self.add_inst(id, NodeInst::NodeGetElemIRef {
            id: id, result_id: result_id, is_ptr: is_ptr, refty: refty, indty: indty, opnd: opnd, index: index
        });
445
446
447
    }

    pub fn new_shiftiref(&mut self, id: MuID, result_id: MuID, is_ptr: bool, refty: MuID, offty: MuID, opnd: MuID, offset: MuID) {
448
449
450
        self.add_inst(id, NodeInst::NodeShiftIRef {
            id: id, result_id: result_id, is_ptr: is_ptr, refty: refty, offty: offty, opnd: opnd, offset: offset
        });
451
452
453
    }

    pub fn new_getvarpartiref(&mut self, id: MuID, result_id: MuID, is_ptr: bool, refty: MuID, opnd: MuID) {
454
455
456
        self.add_inst(id, NodeInst::NodeGetVarPartIRef {
            id: id, result_id: result_id, is_ptr: is_ptr, refty: refty, opnd: opnd
        });
457
458
459
    }

    pub fn new_load(&mut self, id: MuID, result_id: MuID, is_ptr: bool, ord: CMuMemOrd, refty: MuID, loc: MuID, exc_clause: Option<MuID>) {
460
461
462
        self.add_inst(id, NodeInst::NodeLoad {
            id: id, result_id: result_id, is_ptr: is_ptr, ord: ord, refty: refty, loc: loc, exc_clause: exc_clause
        });
463
464
465
    }

    pub fn new_store(&mut self, id: MuID, is_ptr: bool, ord: CMuMemOrd, refty: MuID, loc: MuID, newval: MuID, exc_clause: Option<MuID>) {
466
467
468
        self.add_inst(id, NodeInst::NodeStore {
            id: id, is_ptr: is_ptr, ord: ord, refty: refty, loc: loc, newval: newval, exc_clause: exc_clause
        });
469
470
471
    }

    pub fn new_cmpxchg(&mut self, id: MuID, value_result_id: MuID, succ_result_id: MuID, is_ptr: bool, is_weak: bool, ord_succ: CMuMemOrd, ord_fail: CMuMemOrd, refty: MuID, loc: MuID, expected: MuID, desired: MuID, exc_clause: Option<MuID>) {
472
473
474
        self.add_inst(id, NodeInst::NodeCmpXchg {
            id: id, value_result_id: value_result_id, succ_result_id: succ_result_id, is_ptr: is_ptr, is_weak: is_weak, ord_succ: ord_succ, ord_fail: ord_fail, refty: refty, loc: loc, expected: expected, desired: desired, exc_clause: exc_clause
        });
475
476
477
    }

    pub fn new_atomicrmw(&mut self, id: MuID, result_id: MuID, is_ptr: bool, ord: CMuMemOrd, optr: CMuAtomicRMWOptr, ref_ty: MuID, loc: MuID, opnd: MuID, exc_clause: Option<MuID>) {
478
479
480
        self.add_inst(id, NodeInst::NodeAtomicRMW {
            id: id, result_id: result_id, is_ptr: is_ptr, ord: ord, optr: optr, ref_ty: ref_ty, loc: loc, opnd: opnd, exc_clause: exc_clause
        });
481
482
483
    }

    pub fn new_fence(&mut self, id: MuID, ord: CMuMemOrd) {
484
485
486
        self.add_inst(id, NodeInst::NodeFence {
            id: id, ord: ord,
        });
487
488
489
    }

    pub fn new_trap(&mut self, id: MuID, result_ids: Vec<MuID>, rettys: Vec<MuID>, exc_clause: Option<MuID>, keepalive_clause: Option<MuID>) {
490
491
492
        self.add_inst(id, NodeInst::NodeTrap {
            id: id, result_ids: result_ids, rettys: rettys, exc_clause: exc_clause, keepalive_clause: keepalive_clause
        });
493
494
495
    }

    pub fn new_watchpoint(&mut self, id: MuID, wpid: CMuWPID, result_ids: Vec<MuID>, rettys: Vec<MuID>, dis: MuID, ena: MuID, exc: Option<MuID>, keepalive_clause: Option<MuID>) {
496
497
498
        self.add_inst(id, NodeInst::NodeWatchPoint {
            id: id, wpid: wpid as MuID, result_ids: result_ids, rettys: rettys, dis: dis, ena: ena, exc: exc, keepalive_clause: keepalive_clause
        });
499
500
501
    }

    pub fn new_wpbranch(&mut self, id: MuID, wpid: CMuWPID, dis: MuID, ena: MuID) {
502
503
504
        self.add_inst(id, NodeInst::NodeWPBranch {
            id: id, wpid: wpid as MuID, dis: dis, ena: ena
        });
505
506
507
    }

    pub fn new_ccall(&mut self, id: MuID, result_ids: Vec<MuID>, callconv: CMuCallConv, callee_ty: MuID, sig: MuID, callee: MuID, args: Vec<MuID>, exc_clause: Option<MuID>, keepalive_clause: Option<MuID>) {
508
509
510
        self.add_inst(id, NodeInst::NodeCCall {
            id: id, result_ids: result_ids, callconv: callconv, callee_ty: callee_ty, sig: sig, callee: callee, args: args, exc_clause: exc_clause, keepalive_clause: keepalive_clause
        });
511
512
513
    }

    pub fn new_newthread(&mut self, id: MuID, result_id: MuID, stack: MuID, threadlocal: Option<MuID>, new_stack_clause: MuID, exc_clause: Option<MuID>) {
514
515
516
        self.add_inst(id, NodeInst::NodeNewThread {
            id: id, result_id: result_id, stack: stack, threadlocal: threadlocal, new_stack_clause: new_stack_clause, exc_clause: exc_clause
        });
517
518
519
    }

    pub fn new_swapstack(&mut self, id: MuID, result_ids: Vec<MuID>, swappee: MuID, cur_stack_clause: MuID, new_stack_clause: MuID, exc_clause: Option<MuID>, keepalive_clause: Option<MuID>) {
520
521
522
        self.add_inst(id, NodeInst::NodeSwapStack {
            id: id, result_ids: result_ids, swappee: swappee, cur_stack_clause: cur_stack_clause, new_stack_clause: new_stack_clause, exc_clause: exc_clause, keepalive_clause: keepalive_clause
        });
523
524
525
    }

    pub fn new_comminst(&mut self, id: MuID, result_ids: Vec<MuID>, opcode: CMuCommInst, flags: &[CMuFlag], tys: Vec<MuID>, sigs: Vec<MuID>, args: Vec<MuID>, exc_clause: Option<MuID>, keepalive_clause: Option<MuID>) {
526
527
        self.add_inst(id, NodeInst::NodeCommInst {
            id: id, result_ids: result_ids,
528
            opcode: opcode, flags: vec![], tys: tys, sigs: sigs, args: args,
529
530
            exc_clause: exc_clause, keepalive_clause: keepalive_clause
        });
531
532
533
    }
}

534
type IdPMap<T> = HashMap<MuID, P<T>>;
535

Kunshan Wang's avatar
Kunshan Wang committed
536
537
538
struct BundleLoader<'lb, 'lvm> {
    b: &'lb MuIRBuilder,
    vm: &'lvm VM,
539
    id_name_map: HashMap<MuID, MuName>,
Kunshan Wang's avatar
Kunshan Wang committed
540
541
542
    visited: HashSet<MuID>,
    built_types: IdPMap<MuType>,
    built_sigs: IdPMap<MuFuncSig>,
543
544
545
546
    built_constants: IdPMap<Value>,
    built_globals: IdPMap<Value>,
    built_funcs: IdBMap<MuFunction>,
    built_funcvers: IdBMap<MuFunctionVersion>,
547
    struct_hybrid_id_tags: Vec<(MuID, MuName)>,
Kunshan Wang's avatar
Kunshan Wang committed
548
    built_refi64: Option<P<MuType>>,
549
    built_i1: Option<P<MuType>>,
550
    built_i64: Option<P<MuType>>,
551
    built_funcref_of: IdPMap<MuType>,
552
    built_ref_of: IdPMap<MuType>,
553
554
    built_iref_of: IdPMap<MuType>,
    built_constint_of: HashMap<u64, P<Value>>,
Kunshan Wang's avatar
Kunshan Wang committed
555
}
556

Kunshan Wang's avatar
Kunshan Wang committed
557
fn load_bundle(b: &mut MuIRBuilder) {
558
    let vm = b.get_vm();
559

560
561
    let new_map = b.id_name_map.drain().collect::<HashMap<_,_>>();

Kunshan Wang's avatar
Kunshan Wang committed
562
563
564
    let mut bl = BundleLoader {
        b: b,
        vm: vm,
565
        id_name_map: new_map,
Kunshan Wang's avatar
Kunshan Wang committed
566
        visited: Default::default(),
Kunshan Wang's avatar
Kunshan Wang committed
567
        built_types: Default::default(),
Kunshan Wang's avatar
Kunshan Wang committed
568
        built_sigs: Default::default(),
569
570
        built_constants: Default::default(),
        built_globals: Default::default(),
571
        built_funcs: Default::default(),
572
        built_funcvers: Default::default(),
573
        struct_hybrid_id_tags: Default::default(),
Kunshan Wang's avatar
Kunshan Wang committed
574
        built_refi64: Default::default(),
575
        built_i1: Default::default(),
576
        built_i64: Default::default(),
577
        built_funcref_of: Default::default(),
578
        built_ref_of: Default::default(),
579
580
        built_iref_of: Default::default(),
        built_constint_of: Default::default(),
Kunshan Wang's avatar
Kunshan Wang committed
581
582
583
    };

    bl.load_bundle();
584
585
}

Kunshan Wang's avatar
Kunshan Wang committed
586
587
588
589
#[derive(Default)]
struct FuncCtxBuilder {
    ctx: FunctionContext,
    tree_nodes: IdPMap<TreeNode>,
590
591
}

592
593
const DEFAULT_TRUE_PROB: f32 = 0.6f32;

Kunshan Wang's avatar
Kunshan Wang committed
594
595
impl<'lb, 'lvm> BundleLoader<'lb, 'lvm> {
    fn load_bundle(&mut self) {
596
597
        self.ensure_names();
        self.build_toplevels();
598
        self.add_everything_to_vm();
599
600
    }

Kunshan Wang's avatar
Kunshan Wang committed
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
    fn ensure_refi64(&mut self) -> P<MuType> {
        if let Some(ref refi64) = self.built_refi64 {
            return refi64.clone();
        }

        let id_i64 = self.vm.next_id();
        let id_ref = self.vm.next_id();

        let impl_i64 = P(MuType {
            hdr: MuEntityHeader::unnamed(id_i64),
            v: MuType_::Int(64),
        });

        let impl_ref = P(MuType {
            hdr: MuEntityHeader::unnamed(id_ref),
            v: MuType_::Ref(impl_i64.clone()),
        });

        trace!("Ensure i64 is defined: {} {:?}", id_i64, impl_i64);
        trace!("Ensure ref is defined: {} {:?}", id_ref, impl_ref);

        self.built_types.insert(id_i64, impl_i64);
        self.built_types.insert(id_ref, impl_ref.clone());

        self.built_refi64 = Some(impl_ref.clone());

        impl_ref
    }

630
    fn ensure_i1(&mut self) -> P<MuType> {
631
632
        if let Some(ref impl_ty) = self.built_i1 {
            return impl_ty.clone();
633
634
        }

635
        let id = self.vm.next_id();
636

637
638
        let impl_ty = P(MuType {
            hdr: MuEntityHeader::unnamed(id),
639
640
641
            v: MuType_::Int(1),
        });

642
        trace!("Ensure i1 is defined: {} {:?}", id, impl_ty);
643

644
645
        self.built_types.insert(id, impl_ty.clone());
        self.built_i1 = Some(impl_ty.clone());
646

647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
        impl_ty
    }

    fn ensure_i64(&mut self) -> P<MuType> {
        if let Some(ref impl_ty) = self.built_i64 {
            return impl_ty.clone();
        }

        let id = self.vm.next_id();

        let impl_ty = P(MuType {
            hdr: MuEntityHeader::unnamed(id),
            v: MuType_::Int(64),
        });

        trace!("Ensure i64 is defined: {} {:?}", id, impl_ty);

        self.built_types.insert(id, impl_ty.clone());
        self.built_i64 = Some(impl_ty.clone());

        impl_ty
    }

    fn ensure_constint_of(&mut self, value: u64) -> P<TreeNode> {
        if let Some(c) = self.built_constint_of.get(&value) {
            return self.new_global(c.clone());
        }

        let id = self.vm.next_id();

        let impl_ty = self.ensure_i64();

        let impl_val = P(Value {
            hdr: MuEntityHeader::unnamed(id),
            ty: impl_ty,
            v: Value_::Constant(Constant::Int(value)),
        });

        trace!("Ensure const int is defined: {} {:?}", value, impl_val);

        self.built_constants.insert(id, impl_val.clone());
        self.built_constint_of.insert(value, impl_val.clone());

        self.new_global(impl_val)
691
    }
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
    
    fn ensure_funcref(&mut self, sig_id: MuID) -> P<MuType> {
        if let Some(funcref) = self.built_funcref_of.get(&sig_id) {
            return funcref.clone();
        }

        let sig = self.built_sigs.get(&sig_id).unwrap().clone();

        let id_funcref = self.vm.next_id();

        let impl_funcref = P(MuType {
            hdr: MuEntityHeader::unnamed(id_funcref),
            v: MuType_::FuncRef(sig),
        });

        trace!("Ensure funcref of {} is defined: {} {:?}", sig_id, id_funcref, impl_funcref);

        self.built_types.insert(id_funcref, impl_funcref.clone());
        self.built_funcref_of.insert(sig_id, impl_funcref.clone());

        impl_funcref
    }
714

715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
    fn ensure_type_generic<F>(id: MuID, hint: &str,
                         vm: &VM, cache_map: &mut IdPMap<MuType>, storage_map: &mut IdPMap<MuType>,
                         factory: F) -> P<MuType> where F: Fn(P<MuType>) -> MuType_ {
        if let Some(obj) = cache_map.get(&id) {
            return obj.clone();
        }

        let new_id = vm.next_id();

        let old_obj = storage_map.get(&id).unwrap().clone();

        let impl_type_ = factory(old_obj);

        let new_obj = P(MuType {
            hdr: MuEntityHeader::unnamed(new_id),
            v: impl_type_,
        });

        storage_map.insert(new_id, new_obj.clone());

        trace!("Ensure {} of {} is defined: {:?}", hint, id, new_obj);

        cache_map.insert(new_id, new_obj.clone());

        new_obj
    }

    fn ensure_ref(&mut self, ty_id: MuID) -> P<MuType> {
        BundleLoader::ensure_type_generic(ty_id, "ref", &self.vm, &mut self.built_ref_of, &mut self.built_types, |impl_ty| {
            MuType_::Ref(impl_ty)
        })
    }

748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
    fn ensure_iref(&mut self, ty_id: MuID) -> P<MuType> {
        BundleLoader::ensure_type_generic(ty_id, "iref", &self.vm, &mut self.built_iref_of, &mut self.built_types, |impl_ty| {
            MuType_::IRef(impl_ty)
        })
    }

    fn ensure_uptr(&mut self, ty_id: MuID) -> P<MuType> {
        BundleLoader::ensure_type_generic(ty_id, "uptr", &self.vm, &mut self.built_iref_of, &mut self.built_types, |impl_ty| {
            MuType_::UPtr(impl_ty)
        })
    }

    fn ensure_iref_or_uptr(&mut self, ty_id: MuID, is_ptr: bool) -> P<MuType> {
        if is_ptr {
            self.ensure_uptr(ty_id)
        } else {
            self.ensure_iref(ty_id)
        }
    }

768
    fn name_from_id(id: MuID, hint: &str) -> String {
769
        format!("@uvm.unnamed.{}{}", hint, id)
770
771
772
773
774
775
776
777
778
779
780
    }

    fn ensure_name(&mut self, id: MuID, hint: &str) {
        self.id_name_map.entry(id).or_insert_with(|| {
            let name = BundleLoader::name_from_id(id, hint);
            trace!("Making name for ID {} : {}", id, name);
            name
        });
    }

    fn ensure_names(&mut self) {
781
        // Make sure structs and hybrids have names because names are used to resolve cyclic
782
783
784
785
786
787
        // dependencies.
        for (id, ty) in &self.b.bundle.types {
            match **ty {
                NodeType::TypeStruct { id: _, fieldtys: _ } => { 
                    self.ensure_name(*id, "struct");
                },
788
789
790
                NodeType::TypeHybrid { id: _, fixedtys: _, varty: _ } => { 
                    self.ensure_name(*id, "struct");
                },
791
792
793
                _ => {}
            }
        }
794
795
796
797
798
799
800
801

        for id in self.b.bundle.funcvers.keys() {
            self.ensure_name(*id, "funcver");
        }

        for id in self.b.bundle.bbs.keys() {
            self.ensure_name(*id, "funcver");
        }
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
    }

    fn get_name(&self, id: MuID) -> String {
        self.id_name_map.get(&id).unwrap().clone()
    }

    fn maybe_get_name(&self, id: MuID) -> Option<String> {
        self.id_name_map.get(&id).cloned()
    }

    fn make_mu_entity_header(&self, id: MuID) -> MuEntityHeader {
        match self.maybe_get_name(id) {
            None => MuEntityHeader::unnamed(id),
            Some(name) => MuEntityHeader::named(id, name),
        }
    }

    fn build_toplevels(&mut self) {
Kunshan Wang's avatar
Kunshan Wang committed
820
        for id in self.b.bundle.types.keys() {
821
822
823
824
825
            if !self.visited.contains(id) {
                self.build_type(*id)
            }
        }

826
827
828
        let struct_hybrid_id_tags = self.struct_hybrid_id_tags.drain(..).collect::<Vec<_>>();
        for (id, ref tag) in struct_hybrid_id_tags {
            self.fill_struct_hybrid(id, tag)
Kunshan Wang's avatar
Kunshan Wang committed
829
        }
Kunshan Wang's avatar
Kunshan Wang committed
830
831
832
833
834
835

        for id in self.b.bundle.sigs.keys() {
            if !self.visited.contains(id) {
                self.build_sig(*id)
            }
        }
836

837
838
839
840
        for id in self.b.bundle.consts.keys() {
            if !self.visited.contains(id) {
                self.build_const(*id)
            }
Kunshan Wang's avatar
Kunshan Wang committed
841
        }
842
843
844
845
846
847

        for id in self.b.bundle.funcs.keys() {
            if !self.visited.contains(id) {
                self.build_func(*id)
            }
        }
848
849
850
851

        for id in self.b.bundle.funcvers.keys() {
            self.build_funcver(*id)
        }
Kunshan Wang's avatar
Kunshan Wang committed
852
    }
853

Kunshan Wang's avatar
Kunshan Wang committed
854
855
856
857
    fn build_type(&mut self, id: MuID) {
        self.visited.insert(id);

        let ty = self.b.bundle.types.get(&id).unwrap();
858

Kunshan Wang's avatar
Kunshan Wang committed
859
860
        trace!("Building type {} {:?}", id, ty);

861
862
863
        let hdr = self.make_mu_entity_header(id);

        let impl_ty_ = match **ty {
864
            NodeType::TypeInt { id: _, len } => {
865
                MuType_::Int(len as usize)
Kunshan Wang's avatar
Kunshan Wang committed
866
            },
867
868
869
870
871
872
            NodeType::TypeFloat { id: _ } => {
                MuType_::Float
            },
            NodeType::TypeDouble { id: _ } => {
                MuType_::Double
            },
873
            NodeType::TypeUPtr { id: _, ty: toty } => {
874
875
                let impl_toty = self.ensure_type_rec(toty);
                MuType_::UPtr(impl_toty)
876
            },
877
878
879
            NodeType::TypeUFuncPtr { id: _, sig } => {
                let impl_sig = self.ensure_sig_rec(sig);
                MuType_::UFuncPtr(impl_sig)
Kunshan Wang's avatar
Kunshan Wang committed
880
            },
881
            NodeType::TypeStruct { id: _, fieldtys: _ } => { 
882
                let tag = self.get_name(id);
883
884
885
                self.struct_hybrid_id_tags.push((id, tag.clone()));
                MuType_::mustruct_empty(tag)
                // MuType_::Struct(tag)
Kunshan Wang's avatar
Kunshan Wang committed
886
            },
887
888
889
890
            NodeType::TypeHybrid { id: _, fixedtys: _, varty: _ } => {
                let tag = self.get_name(id);
                self.struct_hybrid_id_tags.push((id, tag.clone()));
                MuType_::hybrid_empty(tag)
891
892
893
//                let impl_fixedtys = fixedtys.iter().map(|t| self.ensure_type_rec(*t)).collect::<Vec<_>>();
//                let impl_varty = self.ensure_type_rec(varty);
//                MuType_::Hybrid(impl_fixedtys, impl_varty)
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
            },
            NodeType::TypeArray { id: _, elemty, len } => { 
                let impl_elemty = self.ensure_type_rec(elemty);
                MuType_::Array(impl_elemty, len)
            },
            NodeType::TypeVector { id: _, elemty, len } => { 
                let impl_elemty = self.ensure_type_rec(elemty);
                MuType_::Vector(impl_elemty, len)
            },
            NodeType::TypeVoid { id: _ } => {
                MuType_::Void
            },
            NodeType::TypeTagRef64 { id: _ } => {
                MuType_::Tagref64
            },
            NodeType::TypeRef { id: _, ty: toty } => {
                let impl_toty = self.ensure_type_rec(toty);
                MuType_::Ref(impl_toty)
            },
            NodeType::TypeIRef { id: _, ty: toty } => {
                let impl_toty = self.ensure_type_rec(toty);
                MuType_::IRef(impl_toty)
            },
            NodeType::TypeWeakRef { id: _, ty: toty } => {
                let impl_toty = self.ensure_type_rec(toty);
                MuType_::WeakRef(impl_toty)
            },
            NodeType::TypeFuncRef { id: _, sig } => {
                let impl_sig = self.ensure_sig_rec(sig);
                MuType_::FuncRef(impl_sig)
            },
            NodeType::TypeThreadRef { id: _ } => {
                MuType_::ThreadRef
            },
            NodeType::TypeStackRef { id: _ } => {
                MuType_::StackRef
            },
Kunshan Wang's avatar
Kunshan Wang committed
931
            ref t => panic!("{:?} not implemented", t),
932
933
934
        };

        let impl_ty = MuType { hdr: hdr, v: impl_ty_ };
Kunshan Wang's avatar
Kunshan Wang committed
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950

        trace!("Type built: {} {:?}", id, impl_ty);

        self.built_types.insert(id, P(impl_ty));
    }

    fn ensure_type_rec(&mut self, id: MuID) -> P<MuType> {
        if self.b.bundle.types.contains_key(&id) {
            if self.visited.contains(&id) {
                match self.built_types.get(&id) {
                    Some(t) => t.clone(),
                    None => panic!("Cyclic types found. id: {}", id)
                }
            } else {
                self.build_type(id);
                self.built_types.get(&id).unwrap().clone()
951
952
            }
        } else {
Kunshan Wang's avatar
Kunshan Wang committed
953
            self.vm.get_type(id)
954
        }
955
    }
Kunshan Wang's avatar
Kunshan Wang committed
956

957
958
959
960
961
962
963
    fn get_built_type(&self, id: MuID) -> P<MuType> {
        match self.built_types.get(&id) {
            Some(t) => t.clone(),
            None => self.vm.get_type(id)
        }
    }

964
    fn fill_struct_hybrid(&mut self, id: MuID, tag: &MuName) {
965
        let ty = self.b.bundle.types.get(&id).unwrap();
966

967
        trace!("Filling struct or hybrid {} {:?}", id, ty);
968
969

        match **ty {
970
            NodeType::TypeStruct { id: _, ref fieldtys } => { 
971
972
973
974
                let fieldtys_impl = fieldtys.iter().map(|fid| {
                    self.ensure_type_rec(*fid)
                }).collect::<Vec<_>>();

975
                MuType_::mustruct_put(tag, fieldtys_impl);
976

977
                trace!("Struct {} filled: {:?}", id,
978
                       STRUCT_TAG_MAP.read().unwrap().get(tag));
979
            },
980
981
982
983
984
985
986
987
988
989
990
991
992
            NodeType::TypeHybrid { id: _, ref fixedtys, varty } => { 
                let fixedtys_impl = fixedtys.iter().map(|fid| {
                    self.ensure_type_rec(*fid)
                }).collect::<Vec<_>>();

                let varty_impl = self.ensure_type_rec(varty);

                MuType_::hybrid_put(tag, fixedtys_impl, varty_impl);

                trace!("Hybrid {} filled: {:?}", id,
                       HYBRID_TAG_MAP.read().unwrap().get(tag));
            },
            ref t => panic!("{} {:?} should be a Struct or Hybrid type", id, ty),
993
994
        }
    }
Kunshan Wang's avatar
Kunshan Wang committed
995
996
997
998
999

    fn build_sig(&mut self, id: MuID) {
        self.visited.insert(id);

        let sig = self.b.bundle.sigs.get(&id).unwrap();
1000

Kunshan Wang's avatar
Kunshan Wang committed
1001
1002
        trace!("Building function signature {} {:?}", id, sig);

1003
1004
        let hdr = self.make_mu_entity_header(id);

Kunshan Wang's avatar
Kunshan Wang committed
1005
        let impl_sig = MuFuncSig{
1006
            hdr: hdr,
Kunshan Wang's avatar
Kunshan Wang committed
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
            ret_tys: sig.rettys.iter().map(|i| self.ensure_type_rec(*i)).collect::<Vec<_>>(),
            arg_tys: sig.paramtys.iter().map(|i| self.ensure_type_rec(*i)).collect::<Vec<_>>(),
        };

        trace!("Function signature built: {} {:?}", id, impl_sig);

        self.built_sigs.insert(id, P(impl_sig));
    }

    fn ensure_sig_rec(&mut self, id: MuID) -> P<MuFuncSig> {
        if self.b.bundle.sigs.contains_key(&id) {
            if self.visited.contains(&id) {
                match self.built_sigs.get(&id) {
                    Some(t) => t.clone(),
                    None => panic!("Cyclic signature found. id: {}", id)
                }
            } else {
                self.build_sig(id);
                self.built_sigs.get(&id).unwrap().clone()
            }
        } else {
            self.vm.get_func_sig(id)
        }
    }
1031
1032
1033
1034
1035

    fn build_const(&mut self, id: MuID) {
        self.visited.insert(id);

        let con = self.b.bundle.consts.get(&id).unwrap();
1036

1037
1038
1039
1040
1041
        trace!("Building constant {} {:?}", id, con);

        let hdr = self.make_mu_entity_header(id);

        let (impl_con, impl_ty) = match **con {
1042
            NodeConst::ConstInt { id: _, ty, value } => {
1043
1044
1045
1046
                let t = self.ensure_type_rec(ty);
                let c = Constant::Int(value);
                (c, t)
            },
1047
            NodeConst::ConstFloat { id: _, ty, value } => {
1048
1049
1050
1051
                let t = self.ensure_type_rec(ty);
                let c = Constant::Float(value);
                (c, t)
            },
1052
            NodeConst::ConstDouble { id: _, ty, value } => {
1053
1054
1055
1056
                let t = self.ensure_type_rec(ty);
                let c = Constant::Double(value);
                (c, t)
            },
1057
            NodeConst::ConstNull { id: _, ty } => {
1058
1059
1060
1061
                let t = self.ensure_type_rec(ty);
                let c = Constant::NullRef;
                (c, t)
            },
1062
1063
1064
1065
1066
            NodeConst::ConstExtern { id: _, ty, ref symbol } => {
                let t = self.ensure_type_rec(ty);
                let c = Constant::ExternSym(symbol.clone());
                (c, t)
            },
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
            ref c => panic!("{:?} not implemented", c),
        };

        let impl_val = Value {
            hdr: hdr,
            ty: impl_ty,
            v: Value_::Constant(impl_con),
        };

        trace!("Constant built: {} {:?}", id, impl_val);

1078
        self.built_constants.insert(id, P(impl_val));
1079
    }
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091

    fn build_func(&mut self, id: MuID) {
        self.visited.insert(id);

        let fun = self.b.bundle.funcs.get(&id).unwrap();

        trace!("Building function {} {:?}", id, fun);

        let hdr = self.make_mu_entity_header(id);
        let impl_sig = self.ensure_sig_rec(fun.sig);

        let impl_fun = MuFunction {
1092
            hdr: hdr.clone(),
1093
1094
1095
1096
1097
1098
1099
            sig: impl_sig,
            cur_ver: None,
            all_vers: Default::default(),
        };

        trace!("Function built: {} {:?}", id, impl_fun);

1100
        self.built_funcs.insert(id, Box::new(impl_fun));
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111

        let impl_ty = self.ensure_funcref(fun.sig);

        let impl_val = Value {
            hdr: hdr,
            ty: impl_ty,
            v: Value_::Constant(Constant::FuncRef(id)),
        };

        trace!("Function value built: {} {:?}", id, impl_val);

1112
        self.built_constants.insert(id, P(impl_val));
1113
    }
1114

1115
1116
1117
1118
1119
1120
1121
1122
1123
    fn get_sig_for_func(&mut self, id: MuID) -> P<MuFuncSig> {
        if let Some(impl_func) = self.built_funcs.get(&id) {
            impl_func.sig.clone()
        } else {
            self.vm.get_func_sig_for_func(id)
        }
    }


1124
1125
    fn build_funcver(&mut self, id: MuID) {
        let fv = self.b.bundle.funcvers.get(&id).unwrap();
1126

1127
1128
1129
        trace!("Building function version {} {:?}", id, fv);

        let hdr = self.make_mu_entity_header(id);
1130
1131
        let func_id = fv.func;
        let impl_sig = self.get_sig_for_func(func_id);
1132

Kunshan Wang's avatar
Kunshan Wang committed
1133
        let mut fcb: FuncCtxBuilder = Default::default();
1134
1135

        let blocks = fv.bbs.iter().map(|bbid| {
Kunshan Wang's avatar
Kunshan Wang committed
1136
            let block = self.build_block(&mut fcb, *bbid);
1137
1138
1139
1140
1141
1142
1143
1144
1145
            (*bbid, block)
        }).collect::<HashMap<MuID, Block>>();

        let entry_id = *fv.bbs.first().unwrap();
        let ctn = FunctionContent {
            entry: entry_id,
            blocks: blocks,
        };

qinsoon's avatar
[wip]    
qinsoon committed
1146
        let impl_fv = MuFunctionVersion::new_(hdr, func_id, impl_sig, ctn, fcb.ctx);
1147
1148
1149

        trace!("Function version built {} {:?}", id, impl_fv);

1150
        self.built_funcvers.insert(id, Box::new(impl_fv));
1151
1152
1153
1154
1155
    }

    /// Copied from ast::ir::*. That was implemented for the previous API which implies mutability.
    /// When we migrate later, we can assume the AST is almost fully immutable, and can be
    /// constructed in a functional recursive-descendent style.
Kunshan Wang's avatar
Kunshan Wang committed
1156
    fn new_ssa(&self, fcb: &mut FuncCtxBuilder, id: MuID, ty: P<MuType>) -> P<TreeNode> {
1157
1158
1159
1160
1161
1162
1163
        let hdr = self.make_mu_entity_header(id);
        let val = P(Value{
            hdr: hdr,
            ty: ty,
            v: Value_::SSAVar(id)
        });

Kunshan Wang's avatar
Kunshan Wang committed
1164
        fcb.ctx.values.insert(id, SSAVarEntry::new(val.clone()));
1165

Kunshan Wang's avatar
Kunshan Wang committed
1166
        let tn = P(TreeNode {
1167
1168
            op: pick_op_code_for_ssa(&val.ty),
            v: TreeNode_::Value(val)
Kunshan Wang's avatar
Kunshan Wang committed
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
        });

        fcb.tree_nodes.insert(id, tn.clone());

        tn
    }

    pub fn new_inst(&self, v: Instruction) -> Box<TreeNode> {
        Box::new(TreeNode{
            op: pick_op_code_for_inst(&v),
            v: TreeNode_::Instruction(v),
        })
    }
1182

Kunshan Wang's avatar
Kunshan Wang committed
1183
1184
1185
1186
    pub fn new_global(&self, v: P<Value>) -> P<TreeNode> {
        P(TreeNode{
            op: pick_op_code_for_value(&v.ty),
            v: TreeNode_::Value(v)
1187
1188
1189
        })
    }

Kunshan Wang's avatar
Kunshan Wang committed
1190
1191
1192
    fn get_treenode(&self, fcb: &FuncCtxBuilder, id: MuID) -> P<TreeNode> {
        if let Some(tn) = fcb.tree_nodes.get(&id) {
            tn.clone()
1193
        } else if let Some(v) = self.built_constants.get(&id) {
Kunshan Wang's avatar
Kunshan Wang committed
1194
1195
1196
1197
1198
1199
1200
            self.new_global(v.clone())
        } else {
            panic!("Operand {} is neither a local var or a global var", id)
        }
    }

    fn build_block(&mut self, fcb: &mut FuncCtxBuilder, id: MuID) -> Block {
1201
1202
1203
1204
        let bb = self.b.bundle.bbs.get(&id).unwrap();

        trace!("Building basic block {} {:?}", id, bb);

1205