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

muirbuilder.rs 86.1 KB
Newer Older
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Copyright 2017 The Australian National University
// 
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 
//     http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

15
use super::common::*;
16
use ast::op::*;
Kunshan Wang's avatar
Kunshan Wang committed
17
use ast::inst::*;
18
use utils::LinkedHashMap;
19
use utils::LinkedHashSet;
20
use std;
21

22
pub struct MuIRBuilder {
23
    /// ref to MuVM
24
    mvm: *const MuVM,
25
26
27
28
29
30
31
32
33
34
35
36

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

37
pub type IdBMap<T> = HashMap<MuID, Box<T>>;
38
39
40
41

/// A trantient bundle, i.e. the bundle being built, but not yet loaded into the MuVM.
#[derive(Default)]
pub struct TrantientBundle {
42
43
44
45
46
47
48
49
50
51
52
53
    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>,
54
55
}

56
57
impl MuIRBuilder {
    pub fn new(mvm: *const MuVM) -> Box<MuIRBuilder> {
58
59
60
61
62
63
64
        Box::new(MuIRBuilder {
            mvm: mvm,
            c_struct: ptr::null_mut(),
            id_name_map: Default::default(),
            bundle: Default::default(),
        })
    }
65

66
    #[inline(always)]
67
68
69
    fn get_mvm<'a, 'b>(&'a mut self) -> &'b MuVM {
        //self.mvm
        unsafe { & *self.mvm }
70
71
    }

72
73
74
75
76
    #[inline(always)]
    fn get_mvm_immutable<'a, 'b>(&'a self) -> &'b MuVM {
        unsafe { & *self.mvm }
    }

77
    #[inline(always)]
78
    fn get_vm<'a, 'b>(&'a mut self) -> &'b VM {
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
        &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
117
        trace!("gen_sym({:?}) -> {}", name, my_id);
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135

        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) {
136
        self.bundle.types.insert(id, Box::new(NodeType::TypeFloat { id: id }));
137
138
139
    }

    pub fn new_type_double(&mut self, id: MuID) {
140
        self.bundle.types.insert(id, Box::new(NodeType::TypeDouble { id: id }));
141
142
143
144
145
146
147
148
    }

    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
149
150
        self.bundle.types.insert(id, Box::new(NodeType::TypeUFuncPtr{ id: id,
            sig: sig }));
151
152
153
154
155
156
157
158
    }

    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) {
159
160
        self.bundle.types.insert(id, Box::new(NodeType::TypeHybrid { id: id,
            fixedtys: fixedtys, varty: varty }));
161
162
163
    }

    pub fn new_type_array(&mut self, id: MuID, elemty: MuID, len: u64) {
164
165
        self.bundle.types.insert(id, Box::new(NodeType::TypeArray { id: id,
            elemty: elemty, len: len as usize }));
166
167
168
    }

    pub fn new_type_vector(&mut self, id: MuID, elemty: MuID, len: u64) {
169
170
        self.bundle.types.insert(id, Box::new(NodeType::TypeVector { id: id,
            elemty: elemty, len: len as usize }));
171
172
173
    }

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

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

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

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

    pub fn new_type_funcref(&mut self, id: MuID, sig: MuID) {
193
194
        self.bundle.types.insert(id, Box::new(NodeType::TypeFuncRef{ id: id,
            sig: sig }));
195
196
197
    }

    pub fn new_type_tagref64(&mut self, id: MuID) {
198
        self.bundle.types.insert(id, Box::new(NodeType::TypeTagRef64 { id: id }));
199
200
201
    }

    pub fn new_type_threadref(&mut self, id: MuID) {
202
        self.bundle.types.insert(id, Box::new(NodeType::TypeThreadRef { id: id }));
203
204
205
    }

    pub fn new_type_stackref(&mut self, id: MuID) {
206
        self.bundle.types.insert(id, Box::new(NodeType::TypeStackRef { id: id }));
207
208
209
    }

    pub fn new_type_framecursorref(&mut self, id: MuID) {
210
        self.bundle.types.insert(id, Box::new(NodeType::TypeFrameCursorRef { id: id }));
211
212
213
    }

    pub fn new_type_irbuilderref(&mut self, id: MuID) {
214
        self.bundle.types.insert(id, Box::new(NodeType::TypeIRBuilderRef { id: id }));
215
216
217
218
219
220
221
222
223
224
225
226
227
    }

    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]) {
228
229
        self.bundle.consts.insert(id, Box::new(NodeConst::ConstIntEx {id: id,
            ty: ty, value: values.to_vec()}));
230
231
232
    }

    pub fn new_const_float(&mut self, id: MuID, ty: MuID, value: f32) {
233
234
        self.bundle.consts.insert(id, Box::new(NodeConst::ConstFloat { id: id,
            ty: ty, value: value }));
235
236
237
    }

    pub fn new_const_double(&mut self, id: MuID, ty: MuID, value: f64) {
238
239
        self.bundle.consts.insert(id, Box::new(NodeConst::ConstDouble { id: id,
            ty: ty, value: value }));
240
241
242
    }

    pub fn new_const_null(&mut self, id: MuID, ty: MuID) {
243
244
        self.bundle.consts.insert(id, Box::new(NodeConst::ConstNull { id: id,
            ty: ty }));
245
246
247
    }

    pub fn new_const_seq(&mut self, id: MuID, ty: MuID, elems: Vec<MuID>) {
248
249
        self.bundle.consts.insert(id, Box::new(NodeConst::ConstSeq { id: id,
            ty: ty, elems: elems }));
250
251
252
    }

    pub fn new_const_extern(&mut self, id: MuID, ty: MuID, symbol: String) {
253
254
        self.bundle.consts.insert(id, Box::new(NodeConst::ConstExtern { id: id,
            ty: ty, symbol: symbol }));
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
    }

    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,
278
279
            nor_param_ids: nor_param_ids, nor_param_types: nor_param_types,
            exc_param_id: exc_param_id, insts: insts }));
280
281
282
    }

    pub fn new_dest_clause(&mut self, id: MuID, dest: MuID, vars: Vec<MuID>) {
283
284
        self.bundle.dest_clauses.insert(id, Box::new(NodeDestClause { id: id,
            dest: dest, vars: vars }));
285
286
287
    }

    pub fn new_exc_clause(&mut self, id: MuID, nor: MuID, exc: MuID) {
288
289
        self.bundle.exc_clauses.insert(id, Box::new(NodeExcClause { id: id,
            nor: nor, exc: exc }));
290
291
292
    }

    pub fn new_keepalive_clause(&mut self, id: MuID, vars: Vec<MuID>) {
293
294
        self.bundle.ka_clauses.insert(id, Box::new(NodeKeepaliveClause { id: id,
            vars: vars }));
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
    }

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

313
314
315
316
317
    #[inline(always)]
    fn add_inst(&mut self, id: MuID, inst: NodeInst) {
        self.bundle.insts.insert(id, Box::new(inst));
    }

318
    pub fn new_binop(&mut self, id: MuID, result_id: MuID, optr: CMuBinOptr, ty: MuID, opnd1: MuID, opnd2: MuID, exc_clause: Option<MuID>) {
319
320
        self.add_inst(id, NodeInst::NodeBinOp {
            id: id, result_id: result_id, status_result_ids: vec![],
321
            optr: optr, flags: 0, ty: ty, opnd1: opnd1, opnd2: opnd2,
322
323
            exc_clause: exc_clause
        });
324
325
326
    }

    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
327
328
329
330
331
        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
        })
332
333
334
    }

    pub fn new_cmp(&mut self, id: MuID, result_id: MuID, optr: CMuCmpOptr, ty: MuID, opnd1: MuID, opnd2: MuID) {
335
336
337
338
        self.add_inst(id, NodeInst::NodeCmp {
            id: id, result_id: result_id,
            optr: optr, ty: ty, opnd1: opnd1, opnd2: opnd2
        });
339
340
341
    }

    pub fn new_conv(&mut self, id: MuID, result_id: MuID, optr: CMuConvOptr, from_ty: MuID, to_ty: MuID, opnd: MuID) {
342
343
344
345
        self.add_inst(id, NodeInst::NodeConv {
            id: id, result_id: result_id,
            optr: optr, from_ty: from_ty, to_ty: to_ty, opnd: opnd
        });
346
347
348
    }

    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) {
349
350
351
352
353
        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
        });
354
355
356
    }

    pub fn new_branch(&mut self, id: MuID, dest: MuID) {
357
358
359
        self.add_inst(id, NodeInst::NodeBranch {
            id: id, dest: dest
        });
360
361
362
    }

    pub fn new_branch2(&mut self, id: MuID, cond: MuID, if_true: MuID, if_false: MuID) {
363
364
365
        self.add_inst(id, NodeInst::NodeBranch2 {
            id: id, cond: cond, if_true: if_true, if_false: if_false
        });
366
367
368
    }

    pub fn new_switch(&mut self, id: MuID, opnd_ty: MuID, opnd: MuID, default_dest: MuID, cases: Vec<MuID>, dests: Vec<MuID>) {
369
370
371
372
        self.add_inst(id, NodeInst::NodeSwitch {
            id: id, opnd_ty: opnd_ty, opnd: opnd, default_dest: default_dest,
            cases: cases, dests: dests
        });
373
374
375
    }

    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>) {
376
377
378
379
380
        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
        });
381
382
383
    }

    pub fn new_tailcall(&mut self, id: MuID, sig: MuID, callee: MuID, args: Vec<MuID>) {
384
385
386
        self.add_inst(id, NodeInst::NodeTailCall {
            id: id, sig: sig, callee: callee, args: args
        });
387
388
389
    }

    pub fn new_ret(&mut self, id: MuID, rvs: Vec<MuID>) {
390
391
392
        self.add_inst(id, NodeInst::NodeRet {
            id: id, rvs: rvs
        });
393
394
395
    }

    pub fn new_throw(&mut self, id: MuID, exc: MuID) {
396
397
398
        self.add_inst(id, NodeInst::NodeThrow {
            id: id, exc: exc
        });
399
400
401
    }

    pub fn new_extractvalue(&mut self, id: MuID, result_id: MuID, strty: MuID, index: c_int, opnd: MuID) {
402
403
404
        self.add_inst(id, NodeInst::NodeExtractValue {
            id: id, result_id: result_id, strty: strty, index: index, opnd: opnd
        });
405
406
407
    }

    pub fn new_insertvalue(&mut self, id: MuID, result_id: MuID, strty: MuID, index: c_int, opnd: MuID, newval: MuID) {
408
409
410
        self.add_inst(id, NodeInst::NodeInsertValue {
            id: id, result_id: result_id, strty: strty, index: index, opnd: opnd, newval: newval
        });
411
412
413
    }

    pub fn new_extractelement(&mut self, id: MuID, result_id: MuID, seqty: MuID, indty: MuID, opnd: MuID, index: MuID) {
414
415
416
        self.add_inst(id, NodeInst::NodeExtractElement {
            id: id, result_id: result_id, seqty: seqty, indty: indty, opnd: opnd, index: index
        });
417
418
419
    }

    pub fn new_insertelement(&mut self, id: MuID, result_id: MuID, seqty: MuID, indty: MuID, opnd: MuID, index: MuID, newval: MuID) {
420
421
422
        self.add_inst(id, NodeInst::NodeInsertElement {
            id: id, result_id: result_id, seqty: seqty, indty: indty, opnd: opnd, index: index, newval: newval
        });
423
424
425
    }

    pub fn new_shufflevector(&mut self, id: MuID, result_id: MuID, vecty: MuID, maskty: MuID, vec1: MuID, vec2: MuID, mask: MuID) {
426
427
428
        self.add_inst(id, NodeInst::NodeShuffleVector {
            id: id, result_id: result_id, vecty: vecty, maskty: maskty, vec1: vec1, vec2: vec2, mask: mask
        });
429
430
431
    }

    pub fn new_new(&mut self, id: MuID, result_id: MuID, allocty: MuID, exc_clause: Option<MuID>) {
432
433
434
        self.add_inst(id, NodeInst::NodeNew {
            id: id, result_id: result_id, allocty: allocty, exc_clause: exc_clause
        });
435
436
437
    }

    pub fn new_newhybrid(&mut self, id: MuID, result_id: MuID, allocty: MuID, lenty: MuID, length: MuID, exc_clause: Option<MuID>) {
438
439
440
        self.add_inst(id, NodeInst::NodeNewHybrid {
            id: id, result_id: result_id, allocty: allocty, lenty: lenty, length: length, exc_clause: exc_clause
        });
441
442
443
    }

    pub fn new_alloca(&mut self, id: MuID, result_id: MuID, allocty: MuID, exc_clause: Option<MuID>) {
444
445
446
        self.add_inst(id, NodeInst::NodeAlloca {
            id: id, result_id: result_id, allocty: allocty, exc_clause: exc_clause
        });
447
448
449
    }

    pub fn new_allocahybrid(&mut self, id: MuID, result_id: MuID, allocty: MuID, lenty: MuID, length: MuID, exc_clause: Option<MuID>) {
450
451
452
        self.add_inst(id, NodeInst::NodeAllocaHybrid {
            id: id, result_id: result_id, allocty: allocty, lenty: lenty, length: length, exc_clause: exc_clause
        });
453
454
455
    }

    pub fn new_getiref(&mut self, id: MuID, result_id: MuID, refty: MuID, opnd: MuID) {
456
457
458
        self.add_inst(id, NodeInst::NodeGetIRef {
            id: id, result_id: result_id, refty: refty, opnd: opnd
        });
459
460
461
    }

    pub fn new_getfieldiref(&mut self, id: MuID, result_id: MuID, is_ptr: bool, refty: MuID, index: c_int, opnd: MuID) {
462
463
464
        self.add_inst(id, NodeInst::NodeGetFieldIRef {
            id: id, result_id: result_id, is_ptr: is_ptr, refty: refty, index: index, opnd: opnd
        });
465
466
467
    }

    pub fn new_getelemiref(&mut self, id: MuID, result_id: MuID, is_ptr: bool, refty: MuID, indty: MuID, opnd: MuID, index: MuID) {
468
469
470
        self.add_inst(id, NodeInst::NodeGetElemIRef {
            id: id, result_id: result_id, is_ptr: is_ptr, refty: refty, indty: indty, opnd: opnd, index: index
        });
471
472
473
    }

    pub fn new_shiftiref(&mut self, id: MuID, result_id: MuID, is_ptr: bool, refty: MuID, offty: MuID, opnd: MuID, offset: MuID) {
474
475
476
        self.add_inst(id, NodeInst::NodeShiftIRef {
            id: id, result_id: result_id, is_ptr: is_ptr, refty: refty, offty: offty, opnd: opnd, offset: offset
        });
477
478
479
    }

    pub fn new_getvarpartiref(&mut self, id: MuID, result_id: MuID, is_ptr: bool, refty: MuID, opnd: MuID) {
480
481
482
        self.add_inst(id, NodeInst::NodeGetVarPartIRef {
            id: id, result_id: result_id, is_ptr: is_ptr, refty: refty, opnd: opnd
        });
483
484
485
    }

    pub fn new_load(&mut self, id: MuID, result_id: MuID, is_ptr: bool, ord: CMuMemOrd, refty: MuID, loc: MuID, exc_clause: Option<MuID>) {
486
487
488
        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
        });
489
490
491
    }

    pub fn new_store(&mut self, id: MuID, is_ptr: bool, ord: CMuMemOrd, refty: MuID, loc: MuID, newval: MuID, exc_clause: Option<MuID>) {
492
493
494
        self.add_inst(id, NodeInst::NodeStore {
            id: id, is_ptr: is_ptr, ord: ord, refty: refty, loc: loc, newval: newval, exc_clause: exc_clause
        });
495
496
497
    }

    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>) {
498
499
500
        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
        });
501
502
503
    }

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

    pub fn new_fence(&mut self, id: MuID, ord: CMuMemOrd) {
510
511
512
        self.add_inst(id, NodeInst::NodeFence {
            id: id, ord: ord,
        });
513
514
515
    }

    pub fn new_trap(&mut self, id: MuID, result_ids: Vec<MuID>, rettys: Vec<MuID>, exc_clause: Option<MuID>, keepalive_clause: Option<MuID>) {
516
517
518
        self.add_inst(id, NodeInst::NodeTrap {
            id: id, result_ids: result_ids, rettys: rettys, exc_clause: exc_clause, keepalive_clause: keepalive_clause
        });
519
520
    }

521
    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>) {
522
        self.add_inst(id, NodeInst::NodeWatchPoint {
523
            id: id, wpid: wpid as MuID, result_ids: result_ids, rettys: rettys, dis: dis, ena: ena, exc: exc, keepalive_clause: keepalive_clause
524
        });
525
526
    }

527
    pub fn new_wpbranch(&mut self, id: MuID, wpid: CMuWPID, dis: MuID, ena: MuID) {
528
        self.add_inst(id, NodeInst::NodeWPBranch {
529
            id: id, wpid: wpid as MuID, dis: dis, ena: ena
530
        });
531
532
533
    }

    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>) {
534
535
536
        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
        });
537
538
539
    }

    pub fn new_newthread(&mut self, id: MuID, result_id: MuID, stack: MuID, threadlocal: Option<MuID>, new_stack_clause: MuID, exc_clause: Option<MuID>) {
540
541
542
        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
        });
543
544
545
    }

    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>) {
546
547
548
        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
        });
549
550
551
    }

    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>) {
552
553
        self.add_inst(id, NodeInst::NodeCommInst {
            id: id, result_ids: result_ids,
554
            opcode: opcode, flags: vec![], tys: tys, sigs: sigs, args: args,
555
556
            exc_clause: exc_clause, keepalive_clause: keepalive_clause
        });
557
558
559
    }
}

560
type IdPMap<T> = HashMap<MuID, P<T>>;
561

Kunshan Wang's avatar
Kunshan Wang committed
562
563
564
struct BundleLoader<'lb, 'lvm> {
    b: &'lb MuIRBuilder,
    vm: &'lvm VM,
565
    id_name_map: HashMap<MuID, MuName>,
Kunshan Wang's avatar
Kunshan Wang committed
566
567
568
    visited: HashSet<MuID>,
    built_types: IdPMap<MuType>,
    built_sigs: IdPMap<MuFuncSig>,
569
570
571
572
    built_constants: IdPMap<Value>,
    built_globals: IdPMap<Value>,
    built_funcs: IdBMap<MuFunction>,
    built_funcvers: IdBMap<MuFunctionVersion>,
573
    struct_hybrid_id_tags: Vec<(MuID, MuName)>,
qinsoon's avatar
qinsoon committed
574
575
576

    built_void: Option<P<MuType>>,
    built_refvoid: Option<P<MuType>>,
Kunshan Wang's avatar
Kunshan Wang committed
577
    built_refi64: Option<P<MuType>>,
578
    built_i1: Option<P<MuType>>,
579
    built_i64: Option<P<MuType>>,
580
581
582
583
584
    built_double: Option<P<MuType>>,
    built_i52: Option<P<MuType>>,
    built_i6: Option<P<MuType>>,
    built_ref_void: Option<P<MuType>>,
    built_tagref64: Option<P<MuType>>,
qinsoon's avatar
qinsoon committed
585

586
    built_funcref_of: IdPMap<MuType>,
587
    built_ref_of: IdPMap<MuType>,
588
    built_iref_of: IdPMap<MuType>,
qinsoon's avatar
qinsoon committed
589
590
    built_uptr_of: IdPMap<MuType>,

591
    built_constint_of: HashMap<u64, P<Value>>,
Kunshan Wang's avatar
Kunshan Wang committed
592
}
593

Kunshan Wang's avatar
Kunshan Wang committed
594
fn load_bundle(b: &mut MuIRBuilder) {
595
    let vm = b.get_vm();
596

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

Kunshan Wang's avatar
Kunshan Wang committed
599
600
601
    let mut bl = BundleLoader {
        b: b,
        vm: vm,
602
        id_name_map: new_map,
Kunshan Wang's avatar
Kunshan Wang committed
603
        visited: Default::default(),
Kunshan Wang's avatar
Kunshan Wang committed
604
        built_types: Default::default(),
Kunshan Wang's avatar
Kunshan Wang committed
605
        built_sigs: Default::default(),
606
607
        built_constants: Default::default(),
        built_globals: Default::default(),
608
        built_funcs: Default::default(),
609
        built_funcvers: Default::default(),
610
        struct_hybrid_id_tags: Default::default(),
qinsoon's avatar
qinsoon committed
611
612
        built_void: Default::default(),
        built_refvoid: Default::default(),
Kunshan Wang's avatar
Kunshan Wang committed
613
        built_refi64: Default::default(),
614
        built_i1: Default::default(),
615
        built_i64: Default::default(),
616
617
618
619
620
        built_double: Default::default(),
        built_i52: Default::default(),
        built_i6: Default::default(),
        built_ref_void: Default::default(),
        built_tagref64: Default::default(),
621
        built_funcref_of: Default::default(),
622
        built_ref_of: Default::default(),
623
        built_iref_of: Default::default(),
qinsoon's avatar
qinsoon committed
624
        built_uptr_of: Default::default(),
625
        built_constint_of: Default::default(),
Kunshan Wang's avatar
Kunshan Wang committed
626
627
628
    };

    bl.load_bundle();
629
630
}

Kunshan Wang's avatar
Kunshan Wang committed
631
632
633
634
#[derive(Default)]
struct FuncCtxBuilder {
    ctx: FunctionContext,
    tree_nodes: IdPMap<TreeNode>,
635
636
}

qinsoon's avatar
qinsoon committed
637
const DEFAULT_TRUE_PROB: f32 = 0.4f32;
638

Kunshan Wang's avatar
Kunshan Wang committed
639
640
impl<'lb, 'lvm> BundleLoader<'lb, 'lvm> {
    fn load_bundle(&mut self) {
641
642
        self.ensure_names();
        self.build_toplevels();
643
        self.add_everything_to_vm();
644
645
    }

qinsoon's avatar
qinsoon committed
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
    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
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
    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
    }

713
    fn ensure_i1(&mut self) -> P<MuType> {
714
715
        if let Some(ref impl_ty) = self.built_i1 {
            return impl_ty.clone();
716
717
        }

718
        let id = self.vm.next_id();
719

720
721
        let impl_ty = P(MuType {
            hdr: MuEntityHeader::unnamed(id),
722
723
724
            v: MuType_::Int(1),
        });

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

727
728
        self.built_types.insert(id, impl_ty.clone());
        self.built_i1 = Some(impl_ty.clone());
729

730
731
732
        impl_ty
    }

733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
    fn ensure_i6(&mut self) -> P<MuType> {
        if let Some(ref impl_ty) = self.built_i6 {
            return impl_ty.clone();
        }

        let id = self.vm.next_id();

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

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

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

        impl_ty
    }
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
    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
    }

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
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855

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

        let id = self.vm.next_id();

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

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

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

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

        let id = self.vm.next_id();

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

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

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

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

        let id = self.vm.next_id();

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

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

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

        impl_ty
    }

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

        let id = self.vm.next_id();

        let impl_void_ty = P(MuType {
            hdr: MuEntityHeader::unnamed(id),
            v: MuType_::Void
        });
        let impl_ty = P(MuType {
            hdr: MuEntityHeader::unnamed(id),
            v: MuType_::Ref(impl_void_ty.clone()),
        });

        trace!("Ensure ref<void> is defined: {} {:?}", id, impl_ty);

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

        impl_ty
    }

856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
    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)
877
    }
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
    
    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
    }
900

901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
    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)
        })
    }

934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
    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)
        }
    }

954
    fn name_from_id(id: MuID, hint: &str) -> String {
955
        format!("@uvm.unnamed.{}{}", hint, id)
956
957
958
959
960
961
962
963
964
965
966
    }

    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) {
967
        // Make sure structs and hybrids have names because names are used to resolve cyclic
968
969
970
971
972
973
        // dependencies.
        for (id, ty) in &self.b.bundle.types {
            match **ty {
                NodeType::TypeStruct { id: _, fieldtys: _ } => { 
                    self.ensure_name(*id, "struct");
                },
974
975
976
                NodeType::TypeHybrid { id: _, fixedtys: _, varty: _ } => { 
                    self.ensure_name(*id, "struct");
                },
977
978
979
                _ => {}
            }
        }
980
981
982
983
984
985
986
987

        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");
        }
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
    }

    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
1006
        for id in self.b.bundle.types.keys() {
1007
1008
1009
1010
1011
            if !self.visited.contains(id) {
                self.build_type(*id)
            }
        }

1012
1013
1014
        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
1015
        }
Kunshan Wang's avatar
Kunshan Wang committed
1016
1017
1018
1019
1020
1021

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

1023
1024
1025
1026
        for id in self.b.bundle.consts.keys() {
            if !self.visited.contains(id) {
                self.build_const(*id)
            }
Kunshan Wang's avatar
Kunshan Wang committed
1027
        }
1028

qinsoon's avatar
qinsoon committed
1029
1030
1031
1032
1033
1034
        for id in self.b.bundle.globals.keys() {
            if !self.visited.contains(id) {
                self.build_global(*id)
            }
        }

1035
1036
1037
1038
1039
        for id in self.b.bundle.funcs.keys() {
            if !self.visited.contains(id) {
                self.build_func(*id)
            }
        }
1040
1041
1042
1043

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

Kunshan Wang's avatar
Kunshan Wang committed
1046
1047
1048
1049
    fn build_type(&mut self, id: MuID) {
        self.visited.insert(id);

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

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

1053
1054
1055
        let hdr = self.make_mu_entity_header(id);

        let impl_ty_ = match **ty {
1056
            NodeType::TypeInt { id: _, len } => {
1057
                MuType_::Int(len as usize)
Kunshan Wang's avatar
Kunshan Wang committed
1058
            },
1059
1060
1061
1062
1063
1064
            NodeType::TypeFloat { id: _ } => {
                MuType_::Float
            },
            NodeType::TypeDouble { id: _ } => {
                MuType_::Double
            },
1065
            NodeType::TypeUPtr { id: _, ty: toty } => {
1066
1067
                let impl_toty = self.ensure_type_rec(toty);
                MuType_::UPtr(impl_toty)
1068
            },
1069
1070
1071
            NodeType::TypeUFuncPtr { id: _, sig } => {
                let impl_sig = self.ensure_sig_rec(sig);
                MuType_::UFuncPtr(impl_sig)
Kunshan Wang's avatar
Kunshan Wang committed
1072
            },
1073
            NodeType::TypeStruct { id: _, fieldtys: _ } => { 
1074
                let tag = self.get_name(id);
1075
1076
1077
                self.struct_hybrid_id_tags.push((id, tag.clone()));
                MuType_::mustruct_empty(tag)
                // MuType_::Struct(tag)
Kunshan Wang's avatar
Kunshan Wang committed
1078
            },
1079
1080
1081
1082
            NodeType::TypeHybrid { id: _, fixedtys: _, varty: _ } => {
                let tag = self.get_name(id);
                self.struct_hybrid_id_tags.push((id, tag.clone()));
                MuType_::hybrid_empty(tag)
1083
1084
1085
//                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)
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
            },
            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
1123
            ref t => panic!("{:?} not implemented", t),
1124
1125
1126
        };

        let impl_ty = MuType { hdr: hdr, v: impl_ty_ };
Kunshan Wang's avatar
Kunshan Wang committed
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142

        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()
1143
1144
            }
        } else {
Kunshan Wang's avatar
Kunshan Wang committed
1145
            self.vm.get_type(id)
1146
        }
1147
    }
Kunshan Wang's avatar
Kunshan Wang committed
1148

1149
1150
1151
1152
1153
1154
1155
    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)
        }
    }

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

1159
        trace!("Filling struct or hybrid {} {:?}", id, ty);
1160
1161

        match **ty {
1162
            NodeType::TypeStruct { id: _, ref fieldtys } => { 
1163
1164
1165
1166
                let fieldtys_impl = fieldtys.iter().map(|fid| {
                    self.ensure_type_rec(*fid)
                }).collect::<Vec<_>>();

1167
                MuType_::mustruct_put(tag, fieldtys_impl);
1168

1169
                trace!("Struct {} filled: {:?}", id,
1170
                       STRUCT_TAG_MAP.read().unwrap().get(tag));
1171
            },
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
            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),
1185
1186
        }
    }
Kunshan Wang's avatar
Kunshan Wang committed
1187
1188
1189
1190
1191

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

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

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

1195
1196
        let hdr = self.make_mu_entity_header(id);

Kunshan Wang's avatar
Kunshan Wang committed
1197
        let impl_sig = MuFuncSig{
1198
            hdr: hdr,
Kunshan Wang's avatar
Kunshan Wang committed
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
            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)
        }
    }
1223
1224
1225
1226
1227

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

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

1229
1230
1231
1232
1233
        trace!("Building constant {} {:?}", id, con);

        let hdr = self.make_mu_entity_header(id);

        let (impl_con, impl_ty) = match **con {
1234
            NodeConst::ConstInt { id: _, ty, value } => {
1235
1236
1237
1238
                let t = self.ensure_type_rec(ty);
                let c = Constant::Int(value);
                (c, t)
            },
1239
1240
1241
1242
1243
            NodeConst::ConstIntEx { id: _, ty, ref value } => {
                let t = self.ensure_type_rec(ty);
                let c = Constant::IntEx(value.clone());
                (c, t)
            },
1244
            NodeConst::ConstFloat { id: _, ty, value } => {
1245
1246
1247
1248
                let t = self.ensure_type_rec(ty);
                let c = Constant::Float(value);
                (c, t)
            },