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
38
39

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

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
            bundle: Default::default()
72
73
        })
    }
74

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

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

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

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

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

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

        my_id
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    pub fn new_bb(
        &mut self,
        id: MuID,
        nor_param_ids: Vec<MuID>,
        nor_param_types: Vec<MuID>,
        exc_param_id: Option<MuID>,
398
        insts: Vec<MuID>
qinsoon's avatar
qinsoon committed
399
400
401
402
403
404
405
406
    ) {
        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,
407
408
                insts: insts
            })
qinsoon's avatar
qinsoon committed
409
        );
410
411
412
    }

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

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

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

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

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

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

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

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

qinsoon's avatar
qinsoon committed
479
480
481
482
483
484
485
486
    pub fn new_binop(
        &mut self,
        id: MuID,
        result_id: MuID,
        optr: CMuBinOptr,
        ty: MuID,
        opnd1: MuID,
        opnd2: MuID,
487
        exc_clause: Option<MuID>
qinsoon's avatar
qinsoon committed
488
489
490
491
492
493
494
495
496
497
498
499
    ) {
        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,
500
501
                exc_clause: exc_clause
            }
qinsoon's avatar
qinsoon committed
502
503
504
505
506
507
508
509
510
511
512
513
514
        );
    }

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

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

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

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

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

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

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

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

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

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

    pub fn new_throw(&mut self, id: MuID, exc: MuID) {
qinsoon's avatar
qinsoon committed
680
681
682
683
684
685
686
687
688
        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,
689
        opnd: MuID
qinsoon's avatar
qinsoon committed
690
691
692
693
694
695
696
697
    ) {
        self.add_inst(
            id,
            NodeInst::NodeExtractValue {
                id: id,
                result_id: result_id,
                strty: strty,
                index: index,
698
699
                opnd: opnd
            }
qinsoon's avatar
qinsoon committed
700
701
702
703
704
705
706
707
708
709
        );
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    pub fn new_fence(&mut self, id: MuID, ord: CMuMemOrd) {
qinsoon's avatar
qinsoon committed
1082
1083
1084
1085
1086
1087
1088
1089
1090
        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>,
1091
        keepalive_clause: Option<MuID>
qinsoon's avatar
qinsoon committed
1092
1093
1094
1095
1096
1097
1098
1099
    ) {
        self.add_inst(
            id,
            NodeInst::NodeTrap {
                id: id,
                result_ids: result_ids,
                rettys: rettys,
                exc_clause: exc_clause,
1100
1101
                keepalive_clause: keepalive_clause
            }
qinsoon's avatar
qinsoon committed
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
        );
    }

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

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

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

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

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

    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>,
1227
        keepalive_clause: Option<MuID>
qinsoon's avatar
qinsoon committed
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
    ) {
        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,
1240
1241
                keepalive_clause: keepalive_clause
            }
qinsoon's avatar
qinsoon committed
1242
        );
1243
1244
1245
    }
}

1246
type IdPMap<T> = HashMap<MuID, P<T>>;
1247

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

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

1274
    built_funcref_of: IdPMap<MuType>,
1275
    built_ref_of: IdPMap<MuType>,
1276
    built_iref_of: IdPMap<MuType>,
qinsoon's avatar
qinsoon committed
1277
1278
    built_uptr_of: IdPMap<MuType>,

1279
1280
    built_constint_of: HashMap<u64, P<Value>>,
    current_sig: Option<P<MuFuncSig>>
Kunshan Wang's avatar
Kunshan Wang committed
1281
}
1282

Kunshan Wang's avatar
Kunshan Wang committed
1283
fn load_bundle(b: &mut MuIRBuilder) {
1284
    let vm = b.get_vm();
1285

qinsoon's avatar
qinsoon committed
1286
    let new_map = b.id_name_map.drain().collect::<HashMap<_, _>>();
1287

Kunshan Wang's avatar
Kunshan Wang committed
1288
1289
1290
    let mut bl = BundleLoader {
        b: b,
        vm: vm,
1291
        id_name_map: new_map,
Kunshan Wang's avatar
Kunshan Wang committed
1292
        visited: Default::default(),
Kunshan Wang's avatar
Kunshan Wang committed
1293
        built_types: Default::default(),
Kunshan Wang's avatar
Kunshan Wang committed
1294
        built_sigs: Default::default(),
1295
1296
        built_constants: Default::default(),
        built_globals: Default::default(),
1297
        built_funcs: Default::default(),
1298
        built_funcvers: Default::default(),
1299
        struct_hybrid_id_tags: Default::default(),
qinsoon's avatar
qinsoon committed
1300
1301
        built_void: Default::default(),
        built_refvoid: Default::default(),
Kunshan Wang's avatar
Kunshan Wang committed
1302
        built_refi64: Default::default(),
1303
        built_i1: Default::default(),
1304
        built_i64: Default::default(),
1305
1306
1307
1308
1309
        built_double: Default::default(),
        built_i52: Default::default(),
        built_i6: Default::default(),
        built_ref_void: Default::default(),
        built_tagref64: Default::default(),
1310
        built_stackref: Default::default(),
1311
        built_threadref: Default::default(),
1312
        built_funcref_of: Default::default(),
1313
        built_ref_of: Default::default(),
1314
        built_iref_of: Default::default(),
qinsoon's avatar
qinsoon committed
1315
        built_uptr_of: Default::default(),
1316
1317
        built_constint_of: Default::default(),
        current_sig: Default::default()