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

muirbuilder.rs 76 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
        &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();

qinsoon's avatar
qinsoon committed
102
        trace!("gen_sym({:?}) -> {}", name, my_id);
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120

        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
    }

    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>) {
qinsoon's avatar
qinsoon committed
311
312
313
314
315
        self.add_inst(id, NodeInst::NodeBinOp {
            id: id, result_id: result_id, status_result_ids: status_result_ids,
            optr: optr, flags: status_flags, ty: ty, opnd1: opnd1, opnd2: opnd2,
            exc_clause: exc_clause
        })
316
317
318
    }

    pub fn new_cmp(&mut self, id: MuID, result_id: MuID, optr: CMuCmpOptr, ty: MuID, opnd1: MuID, opnd2: MuID) {
319
320
321
322
        self.add_inst(id, NodeInst::NodeCmp {
            id: id, result_id: result_id,
            optr: optr, ty: ty, opnd1: opnd1, opnd2: opnd2
        });
323
324
325
    }

    pub fn new_conv(&mut self, id: MuID, result_id: MuID, optr: CMuConvOptr, from_ty: MuID, to_ty: MuID, opnd: MuID) {
326
327
328
329
        self.add_inst(id, NodeInst::NodeConv {
            id: id, result_id: result_id,
            optr: optr, from_ty: from_ty, to_ty: to_ty, opnd: opnd
        });
330
331
332
    }

    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) {
333
334
335
336
337
        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
        });
338
339
340
    }

    pub fn new_branch(&mut self, id: MuID, dest: MuID) {
341
342
343
        self.add_inst(id, NodeInst::NodeBranch {
            id: id, dest: dest
        });
344
345
346
    }

    pub fn new_branch2(&mut self, id: MuID, cond: MuID, if_true: MuID, if_false: MuID) {
347
348
349
        self.add_inst(id, NodeInst::NodeBranch2 {
            id: id, cond: cond, if_true: if_true, if_false: if_false
        });
350
351
352
    }

    pub fn new_switch(&mut self, id: MuID, opnd_ty: MuID, opnd: MuID, default_dest: MuID, cases: Vec<MuID>, dests: Vec<MuID>) {
353
354
355
356
        self.add_inst(id, NodeInst::NodeSwitch {
            id: id, opnd_ty: opnd_ty, opnd: opnd, default_dest: default_dest,
            cases: cases, dests: dests
        });
357
358
359
    }

    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>) {
360
361
362
363
364
        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
        });
365
366
367
    }

    pub fn new_tailcall(&mut self, id: MuID, sig: MuID, callee: MuID, args: Vec<MuID>) {
368
369
370
        self.add_inst(id, NodeInst::NodeTailCall {
            id: id, sig: sig, callee: callee, args: args
        });
371
372
373
    }

    pub fn new_ret(&mut self, id: MuID, rvs: Vec<MuID>) {
374
375
376
        self.add_inst(id, NodeInst::NodeRet {
            id: id, rvs: rvs
        });
377
378
379
    }

    pub fn new_throw(&mut self, id: MuID, exc: MuID) {
380
381
382
        self.add_inst(id, NodeInst::NodeThrow {
            id: id, exc: exc
        });
383
384
385
    }

    pub fn new_extractvalue(&mut self, id: MuID, result_id: MuID, strty: MuID, index: c_int, opnd: MuID) {
386
387
388
        self.add_inst(id, NodeInst::NodeExtractValue {
            id: id, result_id: result_id, strty: strty, index: index, opnd: opnd
        });
389
390
391
    }

    pub fn new_insertvalue(&mut self, id: MuID, result_id: MuID, strty: MuID, index: c_int, opnd: MuID, newval: MuID) {
392
393
394
        self.add_inst(id, NodeInst::NodeInsertValue {
            id: id, result_id: result_id, strty: strty, index: index, opnd: opnd, newval: newval
        });
395
396
397
    }

    pub fn new_extractelement(&mut self, id: MuID, result_id: MuID, seqty: MuID, indty: MuID, opnd: MuID, index: MuID) {
398
399
400
        self.add_inst(id, NodeInst::NodeExtractElement {
            id: id, result_id: result_id, seqty: seqty, indty: indty, opnd: opnd, index: index
        });
401
402
403
    }

    pub fn new_insertelement(&mut self, id: MuID, result_id: MuID, seqty: MuID, indty: MuID, opnd: MuID, index: MuID, newval: MuID) {
404
405
406
        self.add_inst(id, NodeInst::NodeInsertElement {
            id: id, result_id: result_id, seqty: seqty, indty: indty, opnd: opnd, index: index, newval: newval
        });
407
408
409
    }

    pub fn new_shufflevector(&mut self, id: MuID, result_id: MuID, vecty: MuID, maskty: MuID, vec1: MuID, vec2: MuID, mask: MuID) {
410
411
412
        self.add_inst(id, NodeInst::NodeShuffleVector {
            id: id, result_id: result_id, vecty: vecty, maskty: maskty, vec1: vec1, vec2: vec2, mask: mask
        });
413
414
415
    }

    pub fn new_new(&mut self, id: MuID, result_id: MuID, allocty: MuID, exc_clause: Option<MuID>) {
416
417
418
        self.add_inst(id, NodeInst::NodeNew {
            id: id, result_id: result_id, allocty: allocty, exc_clause: exc_clause
        });
419
420
421
    }

    pub fn new_newhybrid(&mut self, id: MuID, result_id: MuID, allocty: MuID, lenty: MuID, length: MuID, exc_clause: Option<MuID>) {
422
423
424
        self.add_inst(id, NodeInst::NodeNewHybrid {
            id: id, result_id: result_id, allocty: allocty, lenty: lenty, length: length, exc_clause: exc_clause
        });
425
426
427
    }

    pub fn new_alloca(&mut self, id: MuID, result_id: MuID, allocty: MuID, exc_clause: Option<MuID>) {
428
429
430
        self.add_inst(id, NodeInst::NodeAlloca {
            id: id, result_id: result_id, allocty: allocty, exc_clause: exc_clause
        });
431
432
433
    }

    pub fn new_allocahybrid(&mut self, id: MuID, result_id: MuID, allocty: MuID, lenty: MuID, length: MuID, exc_clause: Option<MuID>) {
434
435
436
        self.add_inst(id, NodeInst::NodeAllocaHybrid {
            id: id, result_id: result_id, allocty: allocty, lenty: lenty, length: length, exc_clause: exc_clause
        });
437
438
439
    }

    pub fn new_getiref(&mut self, id: MuID, result_id: MuID, refty: MuID, opnd: MuID) {
440
441
442
        self.add_inst(id, NodeInst::NodeGetIRef {
            id: id, result_id: result_id, refty: refty, opnd: opnd
        });
443
444
445
    }

    pub fn new_getfieldiref(&mut self, id: MuID, result_id: MuID, is_ptr: bool, refty: MuID, index: c_int, opnd: MuID) {
446
447
448
        self.add_inst(id, NodeInst::NodeGetFieldIRef {
            id: id, result_id: result_id, is_ptr: is_ptr, refty: refty, index: index, opnd: opnd
        });
449
450
451
    }

    pub fn new_getelemiref(&mut self, id: MuID, result_id: MuID, is_ptr: bool, refty: MuID, indty: MuID, opnd: MuID, index: MuID) {
452
453
454
        self.add_inst(id, NodeInst::NodeGetElemIRef {
            id: id, result_id: result_id, is_ptr: is_ptr, refty: refty, indty: indty, opnd: opnd, index: index
        });
455
456
457
    }

    pub fn new_shiftiref(&mut self, id: MuID, result_id: MuID, is_ptr: bool, refty: MuID, offty: MuID, opnd: MuID, offset: MuID) {
458
459
460
        self.add_inst(id, NodeInst::NodeShiftIRef {
            id: id, result_id: result_id, is_ptr: is_ptr, refty: refty, offty: offty, opnd: opnd, offset: offset
        });
461
462
463
    }

    pub fn new_getvarpartiref(&mut self, id: MuID, result_id: MuID, is_ptr: bool, refty: MuID, opnd: MuID) {
464
465
466
        self.add_inst(id, NodeInst::NodeGetVarPartIRef {
            id: id, result_id: result_id, is_ptr: is_ptr, refty: refty, opnd: opnd
        });
467
468
469
    }

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

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

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

    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>) {
488
489
490
        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
        });
491
492
493
    }

    pub fn new_fence(&mut self, id: MuID, ord: CMuMemOrd) {
494
495
496
        self.add_inst(id, NodeInst::NodeFence {
            id: id, ord: ord,
        });
497
498
499
    }

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

505
    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>) {
506
        self.add_inst(id, NodeInst::NodeWatchPoint {
507
            id: id, wpid: wpid as MuID, result_ids: result_ids, rettys: rettys, dis: dis, ena: ena, exc: exc, keepalive_clause: keepalive_clause
508
        });
509
510
    }

511
    pub fn new_wpbranch(&mut self, id: MuID, wpid: CMuWPID, dis: MuID, ena: MuID) {
512
        self.add_inst(id, NodeInst::NodeWPBranch {
513
            id: id, wpid: wpid as MuID, dis: dis, ena: ena
514
        });
515
516
517
    }

    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>) {
518
519
520
        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
        });
521
522
523
    }

    pub fn new_newthread(&mut self, id: MuID, result_id: MuID, stack: MuID, threadlocal: Option<MuID>, new_stack_clause: MuID, exc_clause: Option<MuID>) {
524
525
526
        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
        });
527
528
529
    }

    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>) {
530
531
532
        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
        });
533
534
535
    }

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

544
type IdPMap<T> = HashMap<MuID, P<T>>;
545

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

    built_void: Option<P<MuType>>,
    built_refvoid: Option<P<MuType>>,
Kunshan Wang's avatar
Kunshan Wang committed
561
    built_refi64: Option<P<MuType>>,
562
    built_i1: Option<P<MuType>>,
563
    built_i64: Option<P<MuType>>,
qinsoon's avatar
qinsoon committed
564

565
    built_funcref_of: IdPMap<MuType>,
566
    built_ref_of: IdPMap<MuType>,
567
    built_iref_of: IdPMap<MuType>,
qinsoon's avatar
qinsoon committed
568
569
    built_uptr_of: IdPMap<MuType>,

570
    built_constint_of: HashMap<u64, P<Value>>,
Kunshan Wang's avatar
Kunshan Wang committed
571
}
572

Kunshan Wang's avatar
Kunshan Wang committed
573
fn load_bundle(b: &mut MuIRBuilder) {
574
    let vm = b.get_vm();
575

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

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

    bl.load_bundle();
603
604
}

Kunshan Wang's avatar
Kunshan Wang committed
605
606
607
608
#[derive(Default)]
struct FuncCtxBuilder {
    ctx: FunctionContext,
    tree_nodes: IdPMap<TreeNode>,
609
610
}

611
612
const DEFAULT_TRUE_PROB: f32 = 0.6f32;

Kunshan Wang's avatar
Kunshan Wang committed
613
614
impl<'lb, 'lvm> BundleLoader<'lb, 'lvm> {
    fn load_bundle(&mut self) {
615
616
        self.ensure_names();
        self.build_toplevels();
617
        self.add_everything_to_vm();
618
619
    }

qinsoon's avatar
qinsoon committed
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
654
655
656
657
    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
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
    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
    }

687
    fn ensure_i1(&mut self) -> P<MuType> {
688
689
        if let Some(ref impl_ty) = self.built_i1 {
            return impl_ty.clone();
690
691
        }

692
        let id = self.vm.next_id();
693

694
695
        let impl_ty = P(MuType {
            hdr: MuEntityHeader::unnamed(id),
696
697
698
            v: MuType_::Int(1),
        });

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

701
702
        self.built_types.insert(id, impl_ty.clone());
        self.built_i1 = Some(impl_ty.clone());
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
744
745
746
747
        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)
748
    }
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
    
    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
    }
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
801
802
803
804
    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)
        })
    }

805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
    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)
        }
    }

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

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

        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");
        }
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
    }

    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
877
        for id in self.b.bundle.types.keys() {
878
879
880
881
882
            if !self.visited.contains(id) {
                self.build_type(*id)
            }
        }

883
884
885
        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
886
        }
Kunshan Wang's avatar
Kunshan Wang committed
887
888
889
890
891
892

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

894
895
896
897
        for id in self.b.bundle.consts.keys() {
            if !self.visited.contains(id) {
                self.build_const(*id)
            }
Kunshan Wang's avatar
Kunshan Wang committed
898
        }
899

qinsoon's avatar
qinsoon committed
900
901
902
903
904
905
        for id in self.b.bundle.globals.keys() {
            if !self.visited.contains(id) {
                self.build_global(*id)
            }
        }

906
907
908
909
910
        for id in self.b.bundle.funcs.keys() {
            if !self.visited.contains(id) {
                self.build_func(*id)
            }
        }
911
912
913
914

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

Kunshan Wang's avatar
Kunshan Wang committed
917
918
919
920
    fn build_type(&mut self, id: MuID) {
        self.visited.insert(id);

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

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

924
925
926
        let hdr = self.make_mu_entity_header(id);

        let impl_ty_ = match **ty {
927
            NodeType::TypeInt { id: _, len } => {
928
                MuType_::Int(len as usize)
Kunshan Wang's avatar
Kunshan Wang committed
929
            },
930
931
932
933
934
935
            NodeType::TypeFloat { id: _ } => {
                MuType_::Float
            },
            NodeType::TypeDouble { id: _ } => {
                MuType_::Double
            },
936
            NodeType::TypeUPtr { id: _, ty: toty } => {
937
938
                let impl_toty = self.ensure_type_rec(toty);
                MuType_::UPtr(impl_toty)
939
            },
940
941
942
            NodeType::TypeUFuncPtr { id: _, sig } => {
                let impl_sig = self.ensure_sig_rec(sig);
                MuType_::UFuncPtr(impl_sig)
Kunshan Wang's avatar
Kunshan Wang committed
943
            },
944
            NodeType::TypeStruct { id: _, fieldtys: _ } => { 
945
                let tag = self.get_name(id);
946
947
948
                self.struct_hybrid_id_tags.push((id, tag.clone()));
                MuType_::mustruct_empty(tag)
                // MuType_::Struct(tag)
Kunshan Wang's avatar
Kunshan Wang committed
949
            },
950
951
952
953
            NodeType::TypeHybrid { id: _, fixedtys: _, varty: _ } => {
                let tag = self.get_name(id);
                self.struct_hybrid_id_tags.push((id, tag.clone()));
                MuType_::hybrid_empty(tag)
954
955
956
//                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)
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
990
991
992
993
            },
            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
994
            ref t => panic!("{:?} not implemented", t),
995
996
997
        };

        let impl_ty = MuType { hdr: hdr, v: impl_ty_ };
Kunshan Wang's avatar
Kunshan Wang committed
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013

        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()
1014
1015
            }
        } else {
Kunshan Wang's avatar
Kunshan Wang committed
1016
            self.vm.get_type(id)
1017
        }
1018
    }
Kunshan Wang's avatar
Kunshan Wang committed
1019

1020
1021
1022
1023
1024
1025
1026
    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)
        }
    }

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

1030
        trace!("Filling struct or hybrid {} {:?}", id, ty);
1031
1032

        match **ty {
1033
            NodeType::TypeStruct { id: _, ref fieldtys } => { 
1034
1035
1036
1037
                let fieldtys_impl = fieldtys.iter().map(|fid| {
                    self.ensure_type_rec(*fid)
                }).collect::<Vec<_>>();

1038
                MuType_::mustruct_put(tag, fieldtys_impl);
1039

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

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

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

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

1066
1067
        let hdr = self.make_mu_entity_header(id);

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

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

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

1100
1101
1102
1103
1104
        trace!("Building constant {} {:?}", id, con);

        let hdr = self.make_mu_entity_header(id);

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

1141
        self.built_constants.insert(id, P(impl_val));
1142
    }
1143

qinsoon's avatar
qinsoon committed
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
    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));
    }

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

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

1184
        self.built_funcs.insert(id, Box::new(impl_fun));
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195

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

1196
        self.built_constants.insert(id, P(impl_val));
1197
    }
1198

1199
1200
1201
1202
1203
1204
1205
1206
1207
    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)
        }
    }


1208
1209
    fn build_funcver(&mut self, id: MuID) {
        let fv = self.b.bundle.funcvers.get(&id).unwrap();
1210