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

muirbuilder.rs 135 KB
Newer Older
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
1
// Copyright 2017 The Australian National University
qinsoon's avatar
qinsoon committed
2
//
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
3
4
5
// 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
qinsoon's avatar
qinsoon committed
6
//
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
7
//     http://www.apache.org/licenses/LICENSE-2.0
qinsoon's avatar
qinsoon committed
8
//
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
9
10
11
12
13
14
// 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
21
use utils::math::align_up;
use utils::bit_utils::bits_ones;
22
use std;
23

24
macro_rules! assert_ir {
25
26
    ($ cond : expr ) => { debug_assert!($cond) };
    ($ cond : expr , $ ( $ arg : tt ) + ) => { debug_assert!($cond, $($arg)+)};
27
28
}

29
pub struct MuIRBuilder {
30
    /// ref to MuVM
31
    mvm: *const MuVM,
32
33
34
35
36
37

    /// 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.
38
39
    id_name_map: HashMap<MuID, MuName>, // Note: some of these entries may be generated internally
    name_id_map: HashMap<MuName, MuID>, // Note: only contains names and ids of things the client gives names to
40
    /// The "transient bundle" includes everything being built here.
41
    bundle: TransientBundle
42
43
}

44
pub type IdBMap<T> = HashMap<MuID, Box<T>>;
45

46
/// A transient bundle, i.e. the bundle being built, but not yet loaded into the MuVM.
47
#[derive(Default)]
48
pub struct TransientBundle {
49
50
51
52
53
54
55
56
57
58
59
    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>,
60
61
    cs_clauses: IdBMap<NodeCurrentStackClause>,
    ns_clauses: IdBMap<NodeNewStackClause>,
62
    ka_clauses: IdBMap<NodeKeepaliveClause>
63
64
}

65
66
impl MuIRBuilder {
    pub fn new(mvm: *const MuVM) -> Box<MuIRBuilder> {
67
68
69
70
        Box::new(MuIRBuilder {
            mvm: mvm,
            c_struct: ptr::null_mut(),
            id_name_map: Default::default(),
71
            name_id_map: Default::default(),
72
            bundle: Default::default()
73
74
        })
    }
75

76
    #[inline(always)]
77
78
    fn get_mvm<'a, 'b>(&'a mut self) -> &'b MuVM {
        //self.mvm
qinsoon's avatar
qinsoon committed
79
        unsafe { &*self.mvm }
80
81
    }

82
83
    #[inline(always)]
    fn get_mvm_immutable<'a, 'b>(&'a self) -> &'b MuVM {
qinsoon's avatar
qinsoon committed
84
        unsafe { &*self.mvm }
85
86
    }

87
    #[inline(always)]
88
    fn get_vm<'a, 'b>(&'a mut self) -> &'b VM {
89
90
91
92
93
94
95
96
97
98
99
        &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;
qinsoon's avatar
qinsoon committed
100
101
102
103
104
        debug!(
            "Deallocating MuIRBuilder {:?} and CMuIRBuilder {:?}...",
            b_ptr,
            c_struct
        );
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
        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();
    }

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

qinsoon's avatar
qinsoon committed
131
        trace!("gen_sym({:?}) -> {}", name, my_id);
132
133

        match name {
qinsoon's avatar
qinsoon committed
134
            None => {}
135
            Some(the_name) => {
136
137
138
                let old_name = self.id_name_map.insert(my_id, the_name.clone());
                let old_id = self.name_id_map.insert(the_name, my_id);
                assert_ir!(old_id.is_none());
qinsoon's avatar
qinsoon committed
139
                debug_assert!(
140
                    old_name.is_none(),
qinsoon's avatar
qinsoon committed
141
142
143
                    "ID already exists: {}, new name: {}, old name: {}",
                    my_id,
                    self.id_name_map.get(&my_id).unwrap(),
144
                    old_name.unwrap()
qinsoon's avatar
qinsoon committed
145
146
                );
            }
147
148
149
150
151
152
        };

        my_id
    }

    pub fn new_type_int(&mut self, id: MuID, len: c_int) {
qinsoon's avatar
qinsoon committed
153
154
155
        self.bundle
            .types
            .insert(id, Box::new(NodeType::TypeInt { id: id, len: len }));
156
157
158
    }

    pub fn new_type_float(&mut self, id: MuID) {
qinsoon's avatar
qinsoon committed
159
160
161
        self.bundle
            .types
            .insert(id, Box::new(NodeType::TypeFloat { id: id }));
162
163
164
    }

    pub fn new_type_double(&mut self, id: MuID) {
qinsoon's avatar
qinsoon committed
165
166
167
        self.bundle
            .types
            .insert(id, Box::new(NodeType::TypeDouble { id: id }));
168
169
170
    }

    pub fn new_type_uptr(&mut self, id: MuID, ty: MuID) {
qinsoon's avatar
qinsoon committed
171
172
173
        self.bundle
            .types
            .insert(id, Box::new(NodeType::TypeUPtr { id: id, ty: ty }));
174
175
176
    }

    pub fn new_type_ufuncptr(&mut self, id: MuID, sig: MuID) {
qinsoon's avatar
qinsoon committed
177
178
179
        self.bundle
            .types
            .insert(id, Box::new(NodeType::TypeUFuncPtr { id: id, sig: sig }));
180
181
182
    }

    pub fn new_type_struct(&mut self, id: MuID, fieldtys: Vec<MuID>) {
qinsoon's avatar
qinsoon committed
183
184
185
186
        self.bundle.types.insert(
            id,
            Box::new(NodeType::TypeStruct {
                id: id,
187
188
                fieldtys: fieldtys
            })
qinsoon's avatar
qinsoon committed
189
        );
190
191
192
    }

    pub fn new_type_hybrid(&mut self, id: MuID, fixedtys: Vec<MuID>, varty: MuID) {
qinsoon's avatar
qinsoon committed
193
194
195
196
197
        self.bundle.types.insert(
            id,
            Box::new(NodeType::TypeHybrid {
                id: id,
                fixedtys: fixedtys,
198
199
                varty: varty
            })
qinsoon's avatar
qinsoon committed
200
        );
201
202
203
    }

    pub fn new_type_array(&mut self, id: MuID, elemty: MuID, len: u64) {
qinsoon's avatar
qinsoon committed
204
205
206
207
208
        self.bundle.types.insert(
            id,
            Box::new(NodeType::TypeArray {
                id: id,
                elemty: elemty,
209
210
                len: len as usize
            })
qinsoon's avatar
qinsoon committed
211
        );
212
213
214
    }

    pub fn new_type_vector(&mut self, id: MuID, elemty: MuID, len: u64) {
qinsoon's avatar
qinsoon committed
215
216
217
218
219
        self.bundle.types.insert(
            id,
            Box::new(NodeType::TypeVector {
                id: id,
                elemty: elemty,
220
221
                len: len as usize
            })
qinsoon's avatar
qinsoon committed
222
        );
223
224
225
    }

    pub fn new_type_void(&mut self, id: MuID) {
qinsoon's avatar
qinsoon committed
226
227
228
        self.bundle
            .types
            .insert(id, Box::new(NodeType::TypeVoid { id: id }));
229
230
231
    }

    pub fn new_type_ref(&mut self, id: MuID, ty: MuID) {
qinsoon's avatar
qinsoon committed
232
233
234
        self.bundle
            .types
            .insert(id, Box::new(NodeType::TypeRef { id: id, ty: ty }));
235
236
237
    }

    pub fn new_type_iref(&mut self, id: MuID, ty: MuID) {
qinsoon's avatar
qinsoon committed
238
239
240
        self.bundle
            .types
            .insert(id, Box::new(NodeType::TypeIRef { id: id, ty: ty }));
241
242
243
    }

    pub fn new_type_weakref(&mut self, id: MuID, ty: MuID) {
qinsoon's avatar
qinsoon committed
244
245
246
        self.bundle
            .types
            .insert(id, Box::new(NodeType::TypeWeakRef { id: id, ty: ty }));
247
248
249
    }

    pub fn new_type_funcref(&mut self, id: MuID, sig: MuID) {
qinsoon's avatar
qinsoon committed
250
251
252
        self.bundle
            .types
            .insert(id, Box::new(NodeType::TypeFuncRef { id: id, sig: sig }));
253
254
255
    }

    pub fn new_type_tagref64(&mut self, id: MuID) {
qinsoon's avatar
qinsoon committed
256
257
258
        self.bundle
            .types
            .insert(id, Box::new(NodeType::TypeTagRef64 { id: id }));
259
260
261
    }

    pub fn new_type_threadref(&mut self, id: MuID) {
qinsoon's avatar
qinsoon committed
262
263
264
        self.bundle
            .types
            .insert(id, Box::new(NodeType::TypeThreadRef { id: id }));
265
266
267
    }

    pub fn new_type_stackref(&mut self, id: MuID) {
qinsoon's avatar
qinsoon committed
268
269
270
        self.bundle
            .types
            .insert(id, Box::new(NodeType::TypeStackRef { id: id }));
271
272
273
    }

    pub fn new_type_framecursorref(&mut self, id: MuID) {
qinsoon's avatar
qinsoon committed
274
275
276
        self.bundle
            .types
            .insert(id, Box::new(NodeType::TypeFrameCursorRef { id: id }));
277
278
279
    }

    pub fn new_type_irbuilderref(&mut self, id: MuID) {
qinsoon's avatar
qinsoon committed
280
281
282
        self.bundle
            .types
            .insert(id, Box::new(NodeType::TypeIRBuilderRef { id: id }));
283
284
285
    }

    pub fn new_funcsig(&mut self, id: MuID, paramtys: Vec<MuID>, rettys: Vec<MuID>) {
qinsoon's avatar
qinsoon committed
286
287
288
289
290
        self.bundle.sigs.insert(
            id,
            Box::new(NodeFuncSig {
                id: id,
                paramtys: paramtys,
291
292
                rettys: rettys
            })
qinsoon's avatar
qinsoon committed
293
        );
294
295
296
    }

    pub fn new_const_int(&mut self, id: MuID, ty: MuID, value: u64) {
qinsoon's avatar
qinsoon committed
297
298
299
300
301
        self.bundle.consts.insert(
            id,
            Box::new(NodeConst::ConstInt {
                id: id,
                ty: ty,
302
303
                value: value
            })
qinsoon's avatar
qinsoon committed
304
        );
305
306
307
    }

    pub fn new_const_int_ex(&mut self, id: MuID, ty: MuID, values: &[u64]) {
qinsoon's avatar
qinsoon committed
308
309
310
311
312
        self.bundle.consts.insert(
            id,
            Box::new(NodeConst::ConstIntEx {
                id: id,
                ty: ty,
313
314
                value: values.to_vec()
            })
qinsoon's avatar
qinsoon committed
315
        );
316
317
318
    }

    pub fn new_const_float(&mut self, id: MuID, ty: MuID, value: f32) {
qinsoon's avatar
qinsoon committed
319
320
321
322
323
        self.bundle.consts.insert(
            id,
            Box::new(NodeConst::ConstFloat {
                id: id,
                ty: ty,
324
325
                value: value
            })
qinsoon's avatar
qinsoon committed
326
        );
327
328
329
    }

    pub fn new_const_double(&mut self, id: MuID, ty: MuID, value: f64) {
qinsoon's avatar
qinsoon committed
330
331
332
333
334
        self.bundle.consts.insert(
            id,
            Box::new(NodeConst::ConstDouble {
                id: id,
                ty: ty,
335
336
                value: value
            })
qinsoon's avatar
qinsoon committed
337
        );
338
339
340
    }

    pub fn new_const_null(&mut self, id: MuID, ty: MuID) {
qinsoon's avatar
qinsoon committed
341
342
343
        self.bundle
            .consts
            .insert(id, Box::new(NodeConst::ConstNull { id: id, ty: ty }));
344
345
346
    }

    pub fn new_const_seq(&mut self, id: MuID, ty: MuID, elems: Vec<MuID>) {
qinsoon's avatar
qinsoon committed
347
348
349
350
351
        self.bundle.consts.insert(
            id,
            Box::new(NodeConst::ConstSeq {
                id: id,
                ty: ty,
352
353
                elems: elems
            })
qinsoon's avatar
qinsoon committed
354
        );
355
356
    }

357
    pub fn new_const_extern(&mut self, id: MuID, ty: MuID, symbol: MuName) {
qinsoon's avatar
qinsoon committed
358
359
360
361
362
        self.bundle.consts.insert(
            id,
            Box::new(NodeConst::ConstExtern {
                id: id,
                ty: ty,
363
364
                symbol: symbol
            })
qinsoon's avatar
qinsoon committed
365
        );
366
367
368
    }

    pub fn new_global_cell(&mut self, id: MuID, ty: MuID) {
qinsoon's avatar
qinsoon committed
369
370
371
        self.bundle
            .globals
            .insert(id, Box::new(NodeGlobalCell { id: id, ty: ty }));
372
373
374
    }

    pub fn new_func(&mut self, id: MuID, sig: MuID) {
qinsoon's avatar
qinsoon committed
375
376
377
        self.bundle
            .funcs
            .insert(id, Box::new(NodeFunc { id: id, sig: sig }));
378
379
380
381
382
383
384
    }

    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>) {
qinsoon's avatar
qinsoon committed
385
386
387
388
389
        self.bundle.funcvers.insert(
            id,
            Box::new(NodeFuncVer {
                id: id,
                func: func,
390
391
                bbs: bbs
            })
qinsoon's avatar
qinsoon committed
392
393
394
395
396
397
398
399
400
        );
    }

    pub fn new_bb(
        &mut self,
        id: MuID,
        nor_param_ids: Vec<MuID>,
        nor_param_types: Vec<MuID>,
        exc_param_id: Option<MuID>,
401
        insts: Vec<MuID>
qinsoon's avatar
qinsoon committed
402
403
404
405
406
407
408
409
    ) {
        self.bundle.bbs.insert(
            id,
            Box::new(NodeBB {
                id: id,
                nor_param_ids: nor_param_ids,
                nor_param_types: nor_param_types,
                exc_param_id: exc_param_id,
410
411
                insts: insts
            })
qinsoon's avatar
qinsoon committed
412
        );
413
414
415
    }

    pub fn new_dest_clause(&mut self, id: MuID, dest: MuID, vars: Vec<MuID>) {
qinsoon's avatar
qinsoon committed
416
417
418
419
420
        self.bundle.dest_clauses.insert(
            id,
            Box::new(NodeDestClause {
                id: id,
                dest: dest,
421
422
                vars: vars
            })
qinsoon's avatar
qinsoon committed
423
        );
424
425
426
    }

    pub fn new_exc_clause(&mut self, id: MuID, nor: MuID, exc: MuID) {
qinsoon's avatar
qinsoon committed
427
428
429
430
431
        self.bundle.exc_clauses.insert(
            id,
            Box::new(NodeExcClause {
                id: id,
                nor: nor,
432
433
                exc: exc
            })
qinsoon's avatar
qinsoon committed
434
        );
435
436
437
    }

    pub fn new_keepalive_clause(&mut self, id: MuID, vars: Vec<MuID>) {
qinsoon's avatar
qinsoon committed
438
439
440
        self.bundle
            .ka_clauses
            .insert(id, Box::new(NodeKeepaliveClause { id: id, vars: vars }));
441
442
443
    }

    pub fn new_csc_ret_with(&mut self, id: MuID, rettys: Vec<MuID>) {
444
445
        self.bundle.cs_clauses.insert(
            id,
446
            Box::new(NodeCurrentStackClause::RetWith {
447
448
449
450
                id: id,
                rettys: rettys
            })
        );
451
452
453
    }

    pub fn new_csc_kill_old(&mut self, id: MuID) {
454
455
456
        self.bundle
            .cs_clauses
            .insert(id, Box::new(NodeCurrentStackClause::KillOld { id: id }));
457
458
459
    }

    pub fn new_nsc_pass_values(&mut self, id: MuID, tys: Vec<MuID>, vars: Vec<MuID>) {
460
461
        self.bundle.ns_clauses.insert(
            id,
462
            Box::new(NodeNewStackClause::PassValues {
463
464
465
466
467
                id: id,
                tys: tys,
                vars: vars
            })
        );
468
469
470
    }

    pub fn new_nsc_throw_exc(&mut self, id: MuID, exc: MuID) {
471
472
        self.bundle.ns_clauses.insert(
            id,
473
            Box::new(NodeNewStackClause::ThrowExc { id: id, exc: exc })
474
        );
475
476
    }

477
478
479
480
481
    #[inline(always)]
    fn add_inst(&mut self, id: MuID, inst: NodeInst) {
        self.bundle.insts.insert(id, Box::new(inst));
    }

qinsoon's avatar
qinsoon committed
482
483
484
485
486
487
488
489
    pub fn new_binop(
        &mut self,
        id: MuID,
        result_id: MuID,
        optr: CMuBinOptr,
        ty: MuID,
        opnd1: MuID,
        opnd2: MuID,
490
        exc_clause: Option<MuID>
qinsoon's avatar
qinsoon committed
491
492
493
494
495
496
497
498
499
500
501
502
    ) {
        self.add_inst(
            id,
            NodeInst::NodeBinOp {
                id: id,
                result_id: result_id,
                status_result_ids: vec![],
                optr: optr,
                flags: 0,
                ty: ty,
                opnd1: opnd1,
                opnd2: opnd2,
503
504
                exc_clause: exc_clause
            }
qinsoon's avatar
qinsoon committed
505
506
507
508
509
510
511
512
513
514
515
516
517
        );
    }

    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,
518
        exc_clause: Option<MuID>
qinsoon's avatar
qinsoon committed
519
520
521
522
523
524
525
526
527
528
529
530
    ) {
        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,
531
532
                exc_clause: exc_clause
            }
qinsoon's avatar
qinsoon committed
533
534
535
536
537
538
539
540
541
542
        )
    }

    pub fn new_cmp(
        &mut self,
        id: MuID,
        result_id: MuID,
        optr: CMuCmpOptr,
        ty: MuID,
        opnd1: MuID,
543
        opnd2: MuID
qinsoon's avatar
qinsoon committed
544
545
546
547
548
549
550
551
552
    ) {
        self.add_inst(
            id,
            NodeInst::NodeCmp {
                id: id,
                result_id: result_id,
                optr: optr,
                ty: ty,
                opnd1: opnd1,
553
554
                opnd2: opnd2
            }
qinsoon's avatar
qinsoon committed
555
556
557
558
559
560
561
562
563
564
        );
    }

    pub fn new_conv(
        &mut self,
        id: MuID,
        result_id: MuID,
        optr: CMuConvOptr,
        from_ty: MuID,
        to_ty: MuID,
565
        opnd: MuID
qinsoon's avatar
qinsoon committed
566
567
568
569
570
571
572
573
574
    ) {
        self.add_inst(
            id,
            NodeInst::NodeConv {
                id: id,
                result_id: result_id,
                optr: optr,
                from_ty: from_ty,
                to_ty: to_ty,
575
576
                opnd: opnd
            }
qinsoon's avatar
qinsoon committed
577
578
579
580
581
582
583
584
585
586
587
        );
    }

    pub fn new_select(
        &mut self,
        id: MuID,
        result_id: MuID,
        cond_ty: MuID,
        opnd_ty: MuID,
        cond: MuID,
        if_true: MuID,
588
        if_false: MuID
qinsoon's avatar
qinsoon committed
589
590
591
592
593
594
595
596
597
598
    ) {
        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,
599
600
                if_false: if_false
            }
qinsoon's avatar
qinsoon committed
601
        );
602
603
604
    }

    pub fn new_branch(&mut self, id: MuID, dest: MuID) {
qinsoon's avatar
qinsoon committed
605
        self.add_inst(id, NodeInst::NodeBranch { id: id, dest: dest });
606
607
608
    }

    pub fn new_branch2(&mut self, id: MuID, cond: MuID, if_true: MuID, if_false: MuID) {
qinsoon's avatar
qinsoon committed
609
610
611
612
613
614
        self.add_inst(
            id,
            NodeInst::NodeBranch2 {
                id: id,
                cond: cond,
                if_true: if_true,
615
616
                if_false: if_false
            }
qinsoon's avatar
qinsoon committed
617
618
619
620
621
622
623
624
625
626
        );
    }

    pub fn new_switch(
        &mut self,
        id: MuID,
        opnd_ty: MuID,
        opnd: MuID,
        default_dest: MuID,
        cases: Vec<MuID>,
627
        dests: Vec<MuID>
qinsoon's avatar
qinsoon committed
628
629
630
631
632
633
634
635
636
    ) {
        self.add_inst(
            id,
            NodeInst::NodeSwitch {
                id: id,
                opnd_ty: opnd_ty,
                opnd: opnd,
                default_dest: default_dest,
                cases: cases,
637
638
                dests: dests
            }
qinsoon's avatar
qinsoon committed
639
640
641
642
643
644
645
646
647
648
649
        );
    }

    pub fn new_call(
        &mut self,
        id: MuID,
        result_ids: Vec<MuID>,
        sig: MuID,
        callee: MuID,
        args: Vec<MuID>,
        exc_clause: Option<MuID>,
650
        keepalive_clause: Option<MuID>
qinsoon's avatar
qinsoon committed
651
652
653
654
655
656
657
658
659
660
    ) {
        self.add_inst(
            id,
            NodeInst::NodeCall {
                id: id,
                result_ids: result_ids,
                sig: sig,
                callee: callee,
                args: args,
                exc_clause: exc_clause,
661
662
                keepalive_clause: keepalive_clause
            }
qinsoon's avatar
qinsoon committed
663
        );
664
665
666
    }

    pub fn new_tailcall(&mut self, id: MuID, sig: MuID, callee: MuID, args: Vec<MuID>) {
qinsoon's avatar
qinsoon committed
667
668
669
670
671
672
        self.add_inst(
            id,
            NodeInst::NodeTailCall {
                id: id,
                sig: sig,
                callee: callee,
673
674
                args: args
            }
qinsoon's avatar
qinsoon committed
675
        );
676
677
678
    }

    pub fn new_ret(&mut self, id: MuID, rvs: Vec<MuID>) {
qinsoon's avatar
qinsoon committed
679
        self.add_inst(id, NodeInst::NodeRet { id: id, rvs: rvs });
680
681
682
    }

    pub fn new_throw(&mut self, id: MuID, exc: MuID) {
qinsoon's avatar
qinsoon committed
683
684
685
686
687
688
689
690
691
        self.add_inst(id, NodeInst::NodeThrow { id: id, exc: exc });
    }

    pub fn new_extractvalue(
        &mut self,
        id: MuID,
        result_id: MuID,
        strty: MuID,
        index: c_int,
692
        opnd: MuID
qinsoon's avatar
qinsoon committed
693
694
695
696
697
698
699
700
    ) {
        self.add_inst(
            id,
            NodeInst::NodeExtractValue {
                id: id,
                result_id: result_id,
                strty: strty,
                index: index,
701
702
                opnd: opnd
            }
qinsoon's avatar
qinsoon committed
703
704
705
706
707
708
709
710
711
712
        );
    }

    pub fn new_insertvalue(
        &mut self,
        id: MuID,
        result_id: MuID,
        strty: MuID,
        index: c_int,
        opnd: MuID,
713
        newval: MuID
qinsoon's avatar
qinsoon committed
714
715
716
717
718
719
720
721
722
    ) {
        self.add_inst(
            id,
            NodeInst::NodeInsertValue {
                id: id,
                result_id: result_id,
                strty: strty,
                index: index,
                opnd: opnd,
723
724
                newval: newval
            }
qinsoon's avatar
qinsoon committed
725
726
727
728
729
730
731
732
733
734
        );
    }

    pub fn new_extractelement(
        &mut self,
        id: MuID,
        result_id: MuID,
        seqty: MuID,
        indty: MuID,
        opnd: MuID,
735
        index: MuID
qinsoon's avatar
qinsoon committed
736
737
738
739
740
741
742
743
744
    ) {
        self.add_inst(
            id,
            NodeInst::NodeExtractElement {
                id: id,
                result_id: result_id,
                seqty: seqty,
                indty: indty,
                opnd: opnd,
745
746
                index: index
            }
qinsoon's avatar
qinsoon committed
747
748
749
750
751
752
753
754
755
756
757
        );
    }

    pub fn new_insertelement(
        &mut self,
        id: MuID,
        result_id: MuID,
        seqty: MuID,
        indty: MuID,
        opnd: MuID,
        index: MuID,
758
        newval: MuID
qinsoon's avatar
qinsoon committed
759
760
761
762
763
764
765
766
767
768
    ) {
        self.add_inst(
            id,
            NodeInst::NodeInsertElement {
                id: id,
                result_id: result_id,
                seqty: seqty,
                indty: indty,
                opnd: opnd,
                index: index,
769
770
                newval: newval
            }
qinsoon's avatar
qinsoon committed
771
772
773
774
775
776
777
778
779
780
781
        );
    }

    pub fn new_shufflevector(
        &mut self,
        id: MuID,
        result_id: MuID,
        vecty: MuID,
        maskty: MuID,
        vec1: MuID,
        vec2: MuID,
782
        mask: MuID
qinsoon's avatar
qinsoon committed
783
784
785
786
787
788
789
790
791
792
    ) {
        self.add_inst(
            id,
            NodeInst::NodeShuffleVector {
                id: id,
                result_id: result_id,
                vecty: vecty,
                maskty: maskty,
                vec1: vec1,
                vec2: vec2,
793
794
                mask: mask
            }
qinsoon's avatar
qinsoon committed
795
        );
796
797
798
    }

    pub fn new_new(&mut self, id: MuID, result_id: MuID, allocty: MuID, exc_clause: Option<MuID>) {
qinsoon's avatar
qinsoon committed
799
800
801
802
803
804
        self.add_inst(
            id,
            NodeInst::NodeNew {
                id: id,
                result_id: result_id,
                allocty: allocty,
805
806
                exc_clause: exc_clause
            }
qinsoon's avatar
qinsoon committed
807
808
809
810
811
812
813
814
815
816
        );
    }

    pub fn new_newhybrid(
        &mut self,
        id: MuID,
        result_id: MuID,
        allocty: MuID,
        lenty: MuID,
        length: MuID,
817
        exc_clause: Option<MuID>
qinsoon's avatar
qinsoon committed
818
819
820
821
822
823
824
825
826
    ) {
        self.add_inst(
            id,
            NodeInst::NodeNewHybrid {
                id: id,
                result_id: result_id,
                allocty: allocty,
                lenty: lenty,
                length: length,
827
828
                exc_clause: exc_clause
            }
qinsoon's avatar
qinsoon committed
829
830
831
832
833
834
835
836
        );
    }

    pub fn new_alloca(
        &mut self,
        id: MuID,
        result_id: MuID,
        allocty: MuID,
837
        exc_clause: Option<MuID>
qinsoon's avatar
qinsoon committed
838
839
840
841
842
843
844
    ) {
        self.add_inst(
            id,
            NodeInst::NodeAlloca {
                id: id,
                result_id: result_id,
                allocty: allocty,
845
846
                exc_clause: exc_clause
            }
qinsoon's avatar
qinsoon committed
847
848
849
850
851
852
853
854
855
856
        );
    }

    pub fn new_allocahybrid(
        &mut self,
        id: MuID,
        result_id: MuID,
        allocty: MuID,
        lenty: MuID,
        length: MuID,
857
        exc_clause: Option<MuID>
qinsoon's avatar
qinsoon committed
858
859
860
861
862
863
864
865
866
    ) {
        self.add_inst(
            id,
            NodeInst::NodeAllocaHybrid {
                id: id,
                result_id: result_id,
                allocty: allocty,
                lenty: lenty,
                length: length,
867
868
                exc_clause: exc_clause
            }
qinsoon's avatar
qinsoon committed
869
        );
870
871
872
    }

    pub fn new_getiref(&mut self, id: MuID, result_id: MuID, refty: MuID, opnd: MuID) {
qinsoon's avatar
qinsoon committed
873
874
875
876
877
878
        self.add_inst(
            id,
            NodeInst::NodeGetIRef {
                id: id,
                result_id: result_id,
                refty: refty,
879
880
                opnd: opnd
            }
qinsoon's avatar
qinsoon committed
881
882
883
884
885
886
887
888
889
890
        );
    }

    pub fn new_getfieldiref(
        &mut self,
        id: MuID,
        result_id: MuID,
        is_ptr: bool,
        refty: MuID,
        index: c_int,
891
        opnd: MuID
qinsoon's avatar
qinsoon committed
892
893
894
895
896
897
898
899
900
    ) {
        self.add_inst(
            id,
            NodeInst::NodeGetFieldIRef {
                id: id,
                result_id: result_id,
                is_ptr: is_ptr,
                refty: refty,
                index: index,
901
902
                opnd: opnd
            }
qinsoon's avatar
qinsoon committed
903
904
905
906
907
908
909
910
911
912
913
        );
    }

    pub fn new_getelemiref(
        &mut self,
        id: MuID,
        result_id: MuID,
        is_ptr: bool,
        refty: MuID,
        indty: MuID,
        opnd: MuID,
914
        index: MuID
qinsoon's avatar
qinsoon committed
915
916
917
918
919
920
921
922
923
924
    ) {
        self.add_inst(
            id,
            NodeInst::NodeGetElemIRef {
                id: id,
                result_id: result_id,
                is_ptr: is_ptr,
                refty: refty,
                indty: indty,
                opnd: opnd,
925
926
                index: index
            }
qinsoon's avatar
qinsoon committed
927
928
929
930
931
932
933
934
935
936
937
        );
    }

    pub fn new_shiftiref(
        &mut self,
        id: MuID,
        result_id: MuID,
        is_ptr: bool,
        refty: MuID,
        offty: MuID,
        opnd: MuID,
938
        offset: MuID
qinsoon's avatar
qinsoon committed
939
940
941
942
943
944
945
946
947
948
    ) {
        self.add_inst(
            id,
            NodeInst::NodeShiftIRef {
                id: id,
                result_id: result_id,
                is_ptr: is_ptr,
                refty: refty,
                offty: offty,
                opnd: opnd,
949
950
                offset: offset
            }
qinsoon's avatar
qinsoon committed
951
952
953
954
955
956
957
958
959
        );
    }

    pub fn new_getvarpartiref(
        &mut self,
        id: MuID,
        result_id: MuID,
        is_ptr: bool,
        refty: MuID,
960
        opnd: MuID
qinsoon's avatar
qinsoon committed
961
962
963
964
965
966
967
968
    ) {
        self.add_inst(
            id,
            NodeInst::NodeGetVarPartIRef {
                id: id,
                result_id: result_id,
                is_ptr: is_ptr,
                refty: refty,
969
970
                opnd: opnd
            }
qinsoon's avatar
qinsoon committed
971
972
973
974
975
976
977
978
979
980
981
        );
    }

    pub fn new_load(
        &mut self,
        id: MuID,
        result_id: MuID,
        is_ptr: bool,
        ord: CMuMemOrd,
        refty: MuID,
        loc: MuID,
982
        exc_clause: Option<MuID>
qinsoon's avatar
qinsoon committed
983
984
985
986
987
988
989
990
991
992
    ) {
        self.add_inst(
            id,
            NodeInst::NodeLoad {
                id: id,
                result_id: result_id,
                is_ptr: is_ptr,
                ord: ord,
                refty: refty,
                loc: loc,
993
994
                exc_clause: exc_clause
            }
qinsoon's avatar
qinsoon committed
995
996
997
998
999
1000
1001
1002
1003
1004
1005
        );
    }

    pub fn new_store(
        &mut self,
        id: MuID,
        is_ptr: bool,
        ord: CMuMemOrd,
        refty: MuID,
        loc: MuID,
        newval: MuID,
1006
        exc_clause: Option<MuID>
qinsoon's avatar
qinsoon committed
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
    ) {
        self.add_inst(
            id,
            NodeInst::NodeStore {
                id: id,
                is_ptr: is_ptr,
                ord: ord,
                refty: refty,
                loc: loc,
                newval: newval,
1017
1018
                exc_clause: exc_clause
            }
qinsoon's avatar
qinsoon committed
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
        );
    }

    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,
1035
        exc_clause: Option<MuID>
qinsoon's avatar
qinsoon committed
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
    ) {
        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,
1051
1052
                exc_clause: exc_clause
            }
qinsoon's avatar
qinsoon committed
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
        );
    }

    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,
1066
        exc_clause: Option<MuID>
qinsoon's avatar
qinsoon committed
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
    ) {
        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,
1079
1080
                exc_clause: exc_clause
            }
qinsoon's avatar
qinsoon committed
1081
        );
1082
1083
1084
    }

    pub fn new_fence(&mut self, id: MuID, ord: CMuMemOrd) {
qinsoon's avatar
qinsoon committed
1085
1086
1087
1088
1089
1090
1091
1092
1093
        self.add_inst(id, NodeInst::NodeFence { id: id, ord: ord });
    }

    pub fn new_trap(
        &mut self,
        id: MuID,
        result_ids: Vec<MuID>,
        rettys: Vec<MuID>,
        exc_clause: Option<MuID>,
1094
        keepalive_clause: Option<MuID>
qinsoon's avatar
qinsoon committed
1095
1096
1097
1098
1099
1100
1101
1102
    ) {
        self.add_inst(
            id,
            NodeInst::NodeTrap {
                id: id,
                result_ids: result_ids,
                rettys: rettys,
                exc_clause: exc_clause,
1103
1104
                keepalive_clause: keepalive_clause
            }
qinsoon's avatar
qinsoon committed
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
        );
    }

    pub fn new_watchpoint(
        &mut self,
        id: MuID,
        wpid: CMuWPID,
        result_ids: Vec<MuID>,
        rettys: Vec<MuID>,
        dis: MuID,
        ena: MuID,
        exc: Option<MuID>,
1117
        keepalive_clause: Option<MuID>
qinsoon's avatar
qinsoon committed
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
    ) {
        self.add_inst(
            id,
            NodeInst::NodeWatchPoint {
                id: id,
                wpid: wpid as MuID,
                result_ids: result_ids,
                rettys: rettys,
                dis: dis,
                ena: ena,
                exc: exc,
1129
1130
                keepalive_clause: keepalive_clause
            }
qinsoon's avatar
qinsoon committed
1131
        );
1132
1133
    }

1134
    pub fn new_wpbranch(&mut self, id: MuID, wpid: CMuWPID, dis: MuID, ena: MuID) {
qinsoon's avatar
qinsoon committed
1135
1136
1137
1138
1139
1140
        self.add_inst(
            id,
            NodeInst::NodeWPBranch {
                id: id,
                wpid: wpid as MuID,
                dis: dis,
1141
1142
                ena: ena
            }
qinsoon's avatar
qinsoon committed
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
        );
    }

    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>,
1156
        keepalive_clause: Option<MuID>
qinsoon's avatar
qinsoon committed
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
    ) {
        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,
1169
1170
                keepalive_clause: keepalive_clause
            }
qinsoon's avatar
qinsoon committed
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
        );
    }

    pub fn new_newthread(
        &mut self,
        id: MuID,
        result_id: MuID,
        stack: MuID,
        threadlocal: Option<MuID>,
        new_stack_clause: MuID,
1181
        exc_clause: Option<MuID>
qinsoon's avatar
qinsoon committed
1182
1183
1184
1185
1186
1187
1188
1189
1190
    ) {
        self.add_inst(
            id,
            NodeInst::NodeNewThread {
                id: id,
                result_id: result_id,
                stack: stack,
                threadlocal: threadlocal,
                new_stack_clause: new_stack_clause,
1191
1192
                exc_clause: exc_clause
            }
qinsoon's avatar
qinsoon committed
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
        );
    }

    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>,
1204
        keepalive_clause: Option<MuID>
qinsoon's avatar
qinsoon committed
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
    ) {
        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,
1215
1216
                keepalive_clause: keepalive_clause
            }
qinsoon's avatar
qinsoon committed
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
        );
    }

    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>,
1230
        keepalive_clause: Option<MuID>
qinsoon's avatar
qinsoon committed
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
    ) {
        self.add_inst(
            id,
            NodeInst::NodeCommInst {
                id: id,
                result_ids: result_ids,
                opcode: opcode,
                flags: vec![],
                tys: tys,
                sigs: sigs,
                args: args,
                exc_clause: exc_clause,
1243
1244
                keepalive_clause: keepalive_clause
            }
qinsoon's avatar
qinsoon committed
1245
        );
1246
1247
1248
    }
}

1249
type IdPMap<T> = HashMap<MuID, P<T>>;
1250

Kunshan Wang's avatar
Kunshan Wang committed
1251
1252
1253
struct BundleLoader<'lb, 'lvm> {
    b: &'lb MuIRBuilder,
    vm: &'lvm VM,
1254
    id_name_map: HashMap<MuID, MuName>,
1255
    name_id_map: HashMap<MuName, MuID>,
Kunshan Wang's avatar
Kunshan Wang committed
1256
1257
1258
    visited: HashSet<MuID>,
    built_types: IdPMap<MuType>,
    built_sigs: IdPMap<MuFuncSig>,
1259
1260
1261
1262
    built_constants: IdPMap<Value>,
    built_globals: IdPMap<Value>,
    built_funcs: IdBMap<MuFunction>,
    built_funcvers: IdBMap<MuFunctionVersion>,
1263
    struct_hybrid_id_tags: Vec<(MuID, MuName)>,
qinsoon's avatar
qinsoon committed
1264
1265
1266

    built_void: Option<P<MuType>>,
    built_refvoid: Option<P<MuType>>,
Kunshan Wang's avatar
Kunshan Wang committed
1267
    built_refi64: Option<P<MuType>>,
1268
    built_i1: Option<P<MuType>>,
1269
    built_i64: Option<P<MuType>>,
1270
1271
1272
1273
1274
    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>>,
1275
    built_stackref: Option<P<MuType>>,
1276
    built_threadref: Option<P<MuType>>,
qinsoon's avatar
qinsoon committed
1277

1278
    built_funcref_of: IdPMap<MuType>,
1279
    built_ref_of: IdPMap<MuType>,
1280
    built_iref_of: IdPMap<MuType>,
qinsoon's avatar
qinsoon committed
1281
1282
    built_uptr_of: IdPMap<MuType>,

1283
1284
    built_constint_of: HashMap<u64, P<Value>>,
    current_sig: Option<P<MuFuncSig>>
Kunshan Wang's avatar
Kunshan Wang committed
1285
}
1286

Kunshan Wang's avatar
Kunshan Wang committed
1287
fn load_bundle(b: &mut MuIRBuilder) {
1288
    let vm = b.get_vm();
1289

1290
1291
    let new_id_name_map = b.id_name_map.drain().collect::<HashMap<_, _>>();
    let new_name_id_map = b.name_id_map.drain().collect::<HashMap<_, _>>();
1292

Kunshan Wang's avatar
Kunshan Wang committed
1293
1294
1295
    let mut bl = BundleLoader {
        b: b,
        vm: vm,
1296
1297
        id_name_map: new_id_name_map,
        name_id_map: new_name_id_map,
Kunshan Wang's avatar
Kunshan Wang committed
1298
        visited: Default::default(),
Kunshan Wang's avatar
Kunshan Wang committed
1299
        built_types: Default::default(),
Kunshan Wang's avatar
Kunshan Wang committed
1300
        built_sigs: Default::default(),
1301
1302
        built_constants: Default::default(),
        built_globals: Default::default(),
1303
        built_funcs: Default::default(),
1304
        built_funcvers: Default::default(),
1305
        struct_hybrid_id_tags: Default::default(),
qinsoon's avatar
qinsoon committed
1306
1307
        built_void: Default::default(),
        built_refvoid: Default::default(),
Kunshan Wang's avatar
Kunshan Wang committed
1308
        built_refi64: Default::default(),
1309
        built_i1: Default::default(),
1310
        built_i64: Default::default(),
1311
1312
1313
1314
1315