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

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

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

    /// 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,
}

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

/// A trantient bundle, i.e. the bundle being built, but not yet loaded into the MuVM.
#[derive(Default)]
pub struct TrantientBundle {
27
28
29
30
31
32
33
34
35
36
37
38
    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>,
39
40
}

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

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

57
58
59
60
61
    #[inline(always)]
    fn get_mvm_immutable<'a, 'b>(&'a self) -> &'b MuVM {
        unsafe { & *self.mvm }
    }

62
    #[inline(always)]
63
    fn get_vm<'a, 'b>(&'a mut self) -> &'b VM {
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
115
116
117
118
119
120
        &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) {
121
        self.bundle.types.insert(id, Box::new(NodeType::TypeFloat { id: id }));
122
123
124
    }

    pub fn new_type_double(&mut self, id: MuID) {
125
        self.bundle.types.insert(id, Box::new(NodeType::TypeDouble { id: id }));
126
127
128
129
130
131
132
133
    }

    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
134
135
        self.bundle.types.insert(id, Box::new(NodeType::TypeUFuncPtr{ id: id,
            sig: sig }));
136
137
138
139
140
141
142
143
    }

    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) {
144
145
        self.bundle.types.insert(id, Box::new(NodeType::TypeHybrid { id: id,
            fixedtys: fixedtys, varty: varty }));
146
147
148
    }

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

    pub fn new_type_vector(&mut self, id: MuID, elemty: MuID, len: u64) {
154
155
        self.bundle.types.insert(id, Box::new(NodeType::TypeVector { id: id,
            elemty: elemty, len: len as usize }));
156
157
158
    }

    pub fn new_type_void(&mut self, id: MuID) {
159
        self.bundle.types.insert(id, Box::new(NodeType::TypeVoid { id: id }));
160
161
162
    }

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

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

    pub fn new_type_weakref(&mut self, id: MuID, ty: MuID) {
173
174
        self.bundle.types.insert(id, Box::new(NodeType::TypeWeakRef{ id: id,
            ty: ty }));
175
176
177
    }

    pub fn new_type_funcref(&mut self, id: MuID, sig: MuID) {
178
179
        self.bundle.types.insert(id, Box::new(NodeType::TypeFuncRef{ id: id,
            sig: sig }));
180
181
182
    }

    pub fn new_type_tagref64(&mut self, id: MuID) {
183
        self.bundle.types.insert(id, Box::new(NodeType::TypeTagRef64 { id: id }));
184
185
186
    }

    pub fn new_type_threadref(&mut self, id: MuID) {
187
        self.bundle.types.insert(id, Box::new(NodeType::TypeThreadRef { id: id }));
188
189
190
    }

    pub fn new_type_stackref(&mut self, id: MuID) {
191
        self.bundle.types.insert(id, Box::new(NodeType::TypeStackRef { id: id }));
192
193
194
    }

    pub fn new_type_framecursorref(&mut self, id: MuID) {
195
        self.bundle.types.insert(id, Box::new(NodeType::TypeFrameCursorRef { id: id }));
196
197
198
    }

    pub fn new_type_irbuilderref(&mut self, id: MuID) {
199
        self.bundle.types.insert(id, Box::new(NodeType::TypeIRBuilderRef { id: id }));
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
    }

    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) {
217
218
        self.bundle.consts.insert(id, Box::new(NodeConst::ConstFloat { id: id,
            ty: ty, value: value }));
219
220
221
    }

    pub fn new_const_double(&mut self, id: MuID, ty: MuID, value: f64) {
222
223
        self.bundle.consts.insert(id, Box::new(NodeConst::ConstDouble { id: id,
            ty: ty, value: value }));
224
225
226
    }

    pub fn new_const_null(&mut self, id: MuID, ty: MuID) {
227
228
        self.bundle.consts.insert(id, Box::new(NodeConst::ConstNull { id: id,
            ty: ty }));
229
230
231
    }

    pub fn new_const_seq(&mut self, id: MuID, ty: MuID, elems: Vec<MuID>) {
232
233
        self.bundle.consts.insert(id, Box::new(NodeConst::ConstSeq { id: id,
            ty: ty, elems: elems }));
234
235
236
    }

    pub fn new_const_extern(&mut self, id: MuID, ty: MuID, symbol: String) {
237
238
        self.bundle.consts.insert(id, Box::new(NodeConst::ConstExtern { id: id,
            ty: ty, symbol: symbol }));
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
    }

    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,
262
263
            nor_param_ids: nor_param_ids, nor_param_types: nor_param_types,
            exc_param_id: exc_param_id, insts: insts }));
264
265
266
    }

    pub fn new_dest_clause(&mut self, id: MuID, dest: MuID, vars: Vec<MuID>) {
267
268
        self.bundle.dest_clauses.insert(id, Box::new(NodeDestClause { id: id,
            dest: dest, vars: vars }));
269
270
271
    }

    pub fn new_exc_clause(&mut self, id: MuID, nor: MuID, exc: MuID) {
272
273
        self.bundle.exc_clauses.insert(id, Box::new(NodeExcClause { id: id,
            nor: nor, exc: exc }));
274
275
276
    }

    pub fn new_keepalive_clause(&mut self, id: MuID, vars: Vec<MuID>) {
277
278
        self.bundle.ka_clauses.insert(id, Box::new(NodeKeepaliveClause { id: id,
            vars: vars }));
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
    }

    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")
    }

297
298
299
300
301
    #[inline(always)]
    fn add_inst(&mut self, id: MuID, inst: NodeInst) {
        self.bundle.insts.insert(id, Box::new(inst));
    }

302
    pub fn new_binop(&mut self, id: MuID, result_id: MuID, optr: CMuBinOptr, ty: MuID, opnd1: MuID, opnd2: MuID, exc_clause: Option<MuID>) {
303
304
        self.add_inst(id, NodeInst::NodeBinOp {
            id: id, result_id: result_id, status_result_ids: vec![],
305
            optr: optr, flags: 0, ty: ty, opnd1: opnd1, opnd2: opnd2,
306
307
            exc_clause: exc_clause
        });
308
309
310
311
312
313
314
    }

    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) {
315
316
317
318
        self.add_inst(id, NodeInst::NodeCmp {
            id: id, result_id: result_id,
            optr: optr, ty: ty, opnd1: opnd1, opnd2: opnd2
        });
319
320
321
    }

    pub fn new_conv(&mut self, id: MuID, result_id: MuID, optr: CMuConvOptr, from_ty: MuID, to_ty: MuID, opnd: MuID) {
322
323
324
325
        self.add_inst(id, NodeInst::NodeConv {
            id: id, result_id: result_id,
            optr: optr, from_ty: from_ty, to_ty: to_ty, opnd: opnd
        });
326
327
328
    }

    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) {
329
330
331
332
333
        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
        });
334
335
336
    }

    pub fn new_branch(&mut self, id: MuID, dest: MuID) {
337
338
339
        self.add_inst(id, NodeInst::NodeBranch {
            id: id, dest: dest
        });
340
341
342
    }

    pub fn new_branch2(&mut self, id: MuID, cond: MuID, if_true: MuID, if_false: MuID) {
343
344
345
        self.add_inst(id, NodeInst::NodeBranch2 {
            id: id, cond: cond, if_true: if_true, if_false: if_false
        });
346
347
348
    }

    pub fn new_switch(&mut self, id: MuID, opnd_ty: MuID, opnd: MuID, default_dest: MuID, cases: Vec<MuID>, dests: Vec<MuID>) {
349
350
351
352
        self.add_inst(id, NodeInst::NodeSwitch {
            id: id, opnd_ty: opnd_ty, opnd: opnd, default_dest: default_dest,
            cases: cases, dests: dests
        });
353
354
355
    }

    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>) {
356
357
358
359
360
        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
        });
361
362
363
    }

    pub fn new_tailcall(&mut self, id: MuID, sig: MuID, callee: MuID, args: Vec<MuID>) {
364
365
366
        self.add_inst(id, NodeInst::NodeTailCall {
            id: id, sig: sig, callee: callee, args: args
        });
367
368
369
    }

    pub fn new_ret(&mut self, id: MuID, rvs: Vec<MuID>) {
370
371
372
        self.add_inst(id, NodeInst::NodeRet {
            id: id, rvs: rvs
        });
373
374
375
    }

    pub fn new_throw(&mut self, id: MuID, exc: MuID) {
376
377
378
        self.add_inst(id, NodeInst::NodeThrow {
            id: id, exc: exc
        });
379
380
381
    }

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

    pub fn new_insertvalue(&mut self, id: MuID, result_id: MuID, strty: MuID, index: c_int, opnd: MuID, newval: MuID) {
388
389
390
        self.add_inst(id, NodeInst::NodeInsertValue {
            id: id, result_id: result_id, strty: strty, index: index, opnd: opnd, newval: newval
        });
391
392
393
    }

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

    pub fn new_insertelement(&mut self, id: MuID, result_id: MuID, seqty: MuID, indty: MuID, opnd: MuID, index: MuID, newval: MuID) {
400
401
402
        self.add_inst(id, NodeInst::NodeInsertElement {
            id: id, result_id: result_id, seqty: seqty, indty: indty, opnd: opnd, index: index, newval: newval
        });
403
404
405
    }

    pub fn new_shufflevector(&mut self, id: MuID, result_id: MuID, vecty: MuID, maskty: MuID, vec1: MuID, vec2: MuID, mask: MuID) {
406
407
408
        self.add_inst(id, NodeInst::NodeShuffleVector {
            id: id, result_id: result_id, vecty: vecty, maskty: maskty, vec1: vec1, vec2: vec2, mask: mask
        });
409
410
411
    }

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

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

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

    pub fn new_allocahybrid(&mut self, id: MuID, result_id: MuID, allocty: MuID, lenty: MuID, length: MuID, exc_clause: Option<MuID>) {
430
431
432
        self.add_inst(id, NodeInst::NodeAllocaHybrid {
            id: id, result_id: result_id, allocty: allocty, lenty: lenty, length: length, exc_clause: exc_clause
        });
433
434
435
    }

    pub fn new_getiref(&mut self, id: MuID, result_id: MuID, refty: MuID, opnd: MuID) {
436
437
438
        self.add_inst(id, NodeInst::NodeGetIRef {
            id: id, result_id: result_id, refty: refty, opnd: opnd
        });
439
440
441
    }

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

    pub fn new_getelemiref(&mut self, id: MuID, result_id: MuID, is_ptr: bool, refty: MuID, indty: MuID, opnd: MuID, index: MuID) {
448
449
450
        self.add_inst(id, NodeInst::NodeGetElemIRef {
            id: id, result_id: result_id, is_ptr: is_ptr, refty: refty, indty: indty, opnd: opnd, index: index
        });
451
452
453
    }

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

    pub fn new_getvarpartiref(&mut self, id: MuID, result_id: MuID, is_ptr: bool, refty: MuID, opnd: MuID) {
460
461
462
        self.add_inst(id, NodeInst::NodeGetVarPartIRef {
            id: id, result_id: result_id, is_ptr: is_ptr, refty: refty, opnd: opnd
        });
463
464
465
    }

    pub fn new_load(&mut self, id: MuID, result_id: MuID, is_ptr: bool, ord: CMuMemOrd, refty: MuID, loc: MuID, exc_clause: Option<MuID>) {
466
467
468
        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
        });
469
470
471
    }

    pub fn new_store(&mut self, id: MuID, is_ptr: bool, ord: CMuMemOrd, refty: MuID, loc: MuID, newval: MuID, exc_clause: Option<MuID>) {
472
473
474
        self.add_inst(id, NodeInst::NodeStore {
            id: id, is_ptr: is_ptr, ord: ord, refty: refty, loc: loc, newval: newval, exc_clause: exc_clause
        });
475
476
477
    }

    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>) {
478
479
480
        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
        });
481
482
483
    }

    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>) {
484
485
486
        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
        });
487
488
489
    }

    pub fn new_fence(&mut self, id: MuID, ord: CMuMemOrd) {
490
491
492
        self.add_inst(id, NodeInst::NodeFence {
            id: id, ord: ord,
        });
493
494
495
    }

    pub fn new_trap(&mut self, id: MuID, result_ids: Vec<MuID>, rettys: Vec<MuID>, exc_clause: Option<MuID>, keepalive_clause: Option<MuID>) {
496
497
498
        self.add_inst(id, NodeInst::NodeTrap {
            id: id, result_ids: result_ids, rettys: rettys, exc_clause: exc_clause, keepalive_clause: keepalive_clause
        });
499
500
501
    }

    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>) {
502
503
504
        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
        });
505
506
507
    }

    pub fn new_wpbranch(&mut self, id: MuID, wpid: CMuWPID, dis: MuID, ena: MuID) {
508
509
510
        self.add_inst(id, NodeInst::NodeWPBranch {
            id: id, wpid: wpid as MuID, dis: dis, ena: ena
        });
511
512
513
    }

    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>) {
514
515
516
        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
        });
517
518
519
    }

    pub fn new_newthread(&mut self, id: MuID, result_id: MuID, stack: MuID, threadlocal: Option<MuID>, new_stack_clause: MuID, exc_clause: Option<MuID>) {
520
521
522
        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
        });
523
524
525
    }

    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>) {
526
527
528
        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
        });
529
530
531
    }

    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>) {
532
533
        self.add_inst(id, NodeInst::NodeCommInst {
            id: id, result_ids: result_ids,
534
            opcode: opcode, flags: vec![], tys: tys, sigs: sigs, args: args,
535
536
            exc_clause: exc_clause, keepalive_clause: keepalive_clause
        });
537
538
539
    }
}

540
type IdPMap<T> = HashMap<MuID, P<T>>;
541

Kunshan Wang's avatar
Kunshan Wang committed
542
543
544
struct BundleLoader<'lb, 'lvm> {
    b: &'lb MuIRBuilder,
    vm: &'lvm VM,
545
    id_name_map: HashMap<MuID, MuName>,
Kunshan Wang's avatar
Kunshan Wang committed
546
547
548
    visited: HashSet<MuID>,
    built_types: IdPMap<MuType>,
    built_sigs: IdPMap<MuFuncSig>,
549
550
551
552
    built_constants: IdPMap<Value>,
    built_globals: IdPMap<Value>,
    built_funcs: IdBMap<MuFunction>,
    built_funcvers: IdBMap<MuFunctionVersion>,
553
    struct_hybrid_id_tags: Vec<(MuID, MuName)>,
qinsoon's avatar
qinsoon committed
554
555
556

    built_void: Option<P<MuType>>,
    built_refvoid: Option<P<MuType>>,
Kunshan Wang's avatar
Kunshan Wang committed
557
    built_refi64: Option<P<MuType>>,
558
    built_i1: Option<P<MuType>>,
559
    built_i64: Option<P<MuType>>,
qinsoon's avatar
qinsoon committed
560

561
    built_funcref_of: IdPMap<MuType>,
562
    built_ref_of: IdPMap<MuType>,
563
    built_iref_of: IdPMap<MuType>,
qinsoon's avatar
qinsoon committed
564
565
    built_uptr_of: IdPMap<MuType>,

566
    built_constint_of: HashMap<u64, P<Value>>,
Kunshan Wang's avatar
Kunshan Wang committed
567
}
568

Kunshan Wang's avatar
Kunshan Wang committed
569
fn load_bundle(b: &mut MuIRBuilder) {
570
    let vm = b.get_vm();
571

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

Kunshan Wang's avatar
Kunshan Wang committed
574
575
576
    let mut bl = BundleLoader {
        b: b,
        vm: vm,
577
        id_name_map: new_map,
Kunshan Wang's avatar
Kunshan Wang committed
578
        visited: Default::default(),
Kunshan Wang's avatar
Kunshan Wang committed
579
        built_types: Default::default(),
Kunshan Wang's avatar
Kunshan Wang committed
580
        built_sigs: Default::default(),
581
582
        built_constants: Default::default(),
        built_globals: Default::default(),
583
        built_funcs: Default::default(),
584
        built_funcvers: Default::default(),
585
        struct_hybrid_id_tags: Default::default(),
qinsoon's avatar
qinsoon committed
586
587
        built_void: Default::default(),
        built_refvoid: Default::default(),
Kunshan Wang's avatar
Kunshan Wang committed
588
        built_refi64: Default::default(),
589
        built_i1: Default::default(),
590
        built_i64: Default::default(),
591
        built_funcref_of: Default::default(),
592
        built_ref_of: Default::default(),
593
        built_iref_of: Default::default(),
qinsoon's avatar
qinsoon committed
594
        built_uptr_of: Default::default(),
595
        built_constint_of: Default::default(),
Kunshan Wang's avatar
Kunshan Wang committed
596
597
598
    };

    bl.load_bundle();
599
600
}

Kunshan Wang's avatar
Kunshan Wang committed
601
602
603
604
#[derive(Default)]
struct FuncCtxBuilder {
    ctx: FunctionContext,
    tree_nodes: IdPMap<TreeNode>,
605
606
}

607
608
const DEFAULT_TRUE_PROB: f32 = 0.6f32;

Kunshan Wang's avatar
Kunshan Wang committed
609
610
impl<'lb, 'lvm> BundleLoader<'lb, 'lvm> {
    fn load_bundle(&mut self) {
611
612
        self.ensure_names();
        self.build_toplevels();
613
        self.add_everything_to_vm();
614
615
    }

qinsoon's avatar
qinsoon committed
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
    fn ensure_void(&mut self) -> P<MuType> {
        if let Some(ref void) = self.built_void {
            return void.clone();
        }

        let id_void = self.vm.next_id();

        let impl_void = P(MuType {
            hdr: MuEntityHeader::unnamed(id_void),
            v: MuType_::Void
        });

        trace!("Ensure void is defined: {} {:?}", id_void, impl_void);

        self.built_types.insert(id_void, impl_void.clone());
        self.built_void = Some(impl_void.clone());

        impl_void
    }

    fn ensure_refvoid(&mut self) -> P<MuType> {
        if let Some(ref refvoid) = self.built_refi64 {
            return refvoid.clone();
        }

        let id_refvoid = self.vm.next_id();

        let id_void = self.ensure_void().id();
        let impl_refvoid = self.ensure_ref(id_void);

        trace!("Ensure refvoid is defined: {} {:?}", id_refvoid, impl_refvoid);

        self.built_types.insert(id_refvoid, impl_refvoid.clone());
        self.built_refvoid = Some(impl_refvoid.clone());

        impl_refvoid
    }

Kunshan Wang's avatar
Kunshan Wang committed
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
    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
    }

683
    fn ensure_i1(&mut self) -> P<MuType> {
684
685
        if let Some(ref impl_ty) = self.built_i1 {
            return impl_ty.clone();
686
687
        }

688
        let id = self.vm.next_id();
689

690
691
        let impl_ty = P(MuType {
            hdr: MuEntityHeader::unnamed(id),
692
693
694
            v: MuType_::Int(1),
        });

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

697
698
        self.built_types.insert(id, impl_ty.clone());
        self.built_i1 = Some(impl_ty.clone());
699

700
701
702
703
704
705
706
707
708
709
710
711
712
713
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
        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)
744
    }
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
    
    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
    }
767

768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
    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)
        })
    }

801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
    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)
        }
    }

821
    fn name_from_id(id: MuID, hint: &str) -> String {
822
        format!("@uvm.unnamed.{}{}", hint, id)
823
824
825
826
827
828
829
830
831
832
833
    }

    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) {
834
        // Make sure structs and hybrids have names because names are used to resolve cyclic
835
836
837
838
839
840
        // dependencies.
        for (id, ty) in &self.b.bundle.types {
            match **ty {
                NodeType::TypeStruct { id: _, fieldtys: _ } => { 
                    self.ensure_name(*id, "struct");
                },
841
842
843
                NodeType::TypeHybrid { id: _, fixedtys: _, varty: _ } => { 
                    self.ensure_name(*id, "struct");
                },
844
845
846
                _ => {}
            }
        }
847
848
849
850
851
852
853
854

        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");
        }
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
    }

    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
873
        for id in self.b.bundle.types.keys() {
874
875
876
877
878
            if !self.visited.contains(id) {
                self.build_type(*id)
            }
        }

879
880
881
        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
882
        }
Kunshan Wang's avatar
Kunshan Wang committed
883
884
885
886
887
888

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

890
891
892
893
        for id in self.b.bundle.consts.keys() {
            if !self.visited.contains(id) {
                self.build_const(*id)
            }
Kunshan Wang's avatar
Kunshan Wang committed
894
        }
895

qinsoon's avatar
qinsoon committed
896
897
898
899
900
901
        for id in self.b.bundle.globals.keys() {
            if !self.visited.contains(id) {
                self.build_global(*id)
            }
        }

902
903
904
905
906
        for id in self.b.bundle.funcs.keys() {
            if !self.visited.contains(id) {
                self.build_func(*id)
            }
        }
907
908
909
910

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

Kunshan Wang's avatar
Kunshan Wang committed
913
914
915
916
    fn build_type(&mut self, id: MuID) {
        self.visited.insert(id);

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

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

920
921
922
        let hdr = self.make_mu_entity_header(id);

        let impl_ty_ = match **ty {
923
            NodeType::TypeInt { id: _, len } => {
924
                MuType_::Int(len as usize)
Kunshan Wang's avatar
Kunshan Wang committed
925
            },
926
927
928
929
930
931
            NodeType::TypeFloat { id: _ } => {
                MuType_::Float
            },
            NodeType::TypeDouble { id: _ } => {
                MuType_::Double
            },
932
            NodeType::TypeUPtr { id: _, ty: toty } => {
933
934
                let impl_toty = self.ensure_type_rec(toty);
                MuType_::UPtr(impl_toty)
935
            },
936
937
938
            NodeType::TypeUFuncPtr { id: _, sig } => {
                let impl_sig = self.ensure_sig_rec(sig);
                MuType_::UFuncPtr(impl_sig)
Kunshan Wang's avatar
Kunshan Wang committed
939
            },
940
            NodeType::TypeStruct { id: _, fieldtys: _ } => { 
941
                let tag = self.get_name(id);
942
943
944
                self.struct_hybrid_id_tags.push((id, tag.clone()));
                MuType_::mustruct_empty(tag)
                // MuType_::Struct(tag)
Kunshan Wang's avatar
Kunshan Wang committed
945
            },
946
947
948
949
            NodeType::TypeHybrid { id: _, fixedtys: _, varty: _ } => {
                let tag = self.get_name(id);
                self.struct_hybrid_id_tags.push((id, tag.clone()));
                MuType_::hybrid_empty(tag)
950
951
952
//                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)
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
            },
            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
990
            ref t => panic!("{:?} not implemented", t),
991
992
993
        };

        let impl_ty = MuType { hdr: hdr, v: impl_ty_ };
Kunshan Wang's avatar
Kunshan Wang committed
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009

        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()
1010
1011
            }
        } else {
Kunshan Wang's avatar
Kunshan Wang committed
1012
            self.vm.get_type(id)
1013
        }
1014
    }
Kunshan Wang's avatar
Kunshan Wang committed
1015

1016
1017
1018
1019
1020
1021
1022
    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)
        }
    }

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

1026
        trace!("Filling struct or hybrid {} {:?}", id, ty);
1027
1028

        match **ty {
1029
            NodeType::TypeStruct { id: _, ref fieldtys } => { 
1030
1031
1032
1033
                let fieldtys_impl = fieldtys.iter().map(|fid| {
                    self.ensure_type_rec(*fid)
                }).collect::<Vec<_>>();

1034
                MuType_::mustruct_put(tag, fieldtys_impl);
1035

1036
                trace!("Struct {} filled: {:?}", id,
1037
                       STRUCT_TAG_MAP.read().unwrap().get(tag));
1038
            },
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
            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),
1052
1053
        }
    }
Kunshan Wang's avatar
Kunshan Wang committed
1054
1055
1056
1057
1058

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

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

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

1062
1063
        let hdr = self.make_mu_entity_header(id);

Kunshan Wang's avatar
Kunshan Wang committed
1064
        let impl_sig = MuFuncSig{
1065
            hdr: hdr,
Kunshan Wang's avatar
Kunshan Wang committed
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
            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)
        }
    }
1090
1091
1092
1093
1094

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

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

1096
1097
1098
1099
1100
        trace!("Building constant {} {:?}", id, con);

        let hdr = self.make_mu_entity_header(id);

        let (impl_con, impl_ty) = match **con {
1101
            NodeConst::ConstInt { id: _, ty, value } => {
1102
1103
1104
1105
                let t = self.ensure_type_rec(ty);
                let c = Constant::Int(value);
                (c, t)
            },
1106
            NodeConst::ConstFloat { id: _, ty, value } => {
1107
1108
1109
1110
                let t = self.ensure_type_rec(ty);
                let c = Constant::Float(value);
                (c, t)
            },
1111
            NodeConst::ConstDouble { id: _, ty, value } => {
1112
1113
1114
1115
                let t = self.ensure_type_rec(ty);
                let c = Constant::Double(value);
                (c, t)
            },
1116
            NodeConst::ConstNull { id: _, ty } => {
1117
1118
1119
1120
                let t = self.ensure_type_rec(ty);
                let c = Constant::NullRef;
                (c, t)
            },
1121
1122
1123
1124
1125
            NodeConst::ConstExtern { id: _, ty, ref symbol } => {
                let t = self.ensure_type_rec(ty);
                let c = Constant::ExternSym(symbol.clone());
                (c, t)
            },
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
            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);

1137
        self.built_constants.insert(id, P(impl_val));
1138
    }
1139

qinsoon's avatar
qinsoon committed
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
    fn build_global(&mut self, id: MuID) {
        self.visited.insert(id);

        let global = self.b.bundle.globals.get(&id).unwrap();

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

        let hdr = self.make_mu_entity_header(id);
        let impl_ty = self.ensure_type_rec(global.ty); // global type

        let impl_val = Value {
            hdr: hdr,
            ty: self.ensure_iref(impl_ty.id()), // iref to global
            v: Value_::Global(impl_ty)
        };

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

        self.built_globals.insert(id, P(impl_val));
    }

1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
    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 {
1172
            hdr: hdr.clone(),
1173
1174
1175
1176
1177
1178
1179
            sig: impl_sig,
            cur_ver: None,
            all_vers: Default::default(),
        };

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

1180
        self.built_funcs.insert(id, Box::new(impl_fun));
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191

        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);

1192
        self.built_constants.insert(id, P(impl_val));
1193
    }
1194

1195
1196
1197
1198
1199
1200
1201
1202
1203
    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)
        }
    }


1204
1205
    fn build_funcver(&mut self, id: MuID) {
        let fv = self.b.bundle.funcvers.get(&id).unwrap();
1206

1207
1208
1209
        trace!("Building function version {} {:?}", id, fv);

        let hdr = self.make_mu_entity_header(id);
1210
1211
        let func_id = fv.func;
        let impl_sig = self.get_sig_for_func(func_id);
1212

Kunshan Wang's avatar
Kunshan Wang committed
1213
        let mut fcb: FuncCtxBuilder = Default::default();
1214
1215

        let blocks = fv.bbs.iter().map(|bbid| {
Kunshan Wang's avatar
Kunshan Wang committed
1216
            let block = self.build_block(&mut fcb, *bbid);
1217
            (*bbid, block)
1218
        }).collect::<LinkedHashMap<MuID, Block>>();