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

muirbuilder.rs 103 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
use std;
21

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

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

33
    /// The "transient bundle" includes everything being built here.
34
    bundle: TransientBundle
35
36
}

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

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

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

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

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

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
        &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
90
91
92
93
94
        debug!(
            "Deallocating MuIRBuilder {:?} and CMuIRBuilder {:?}...",
            b_ptr,
            c_struct
        );
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
        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
121
        trace!("gen_sym({:?}) -> {}", name, my_id);
122
123

        match name {
qinsoon's avatar
qinsoon committed
124
            None => {}
125
126
            Some(the_name) => {
                let old = self.id_name_map.insert(my_id, the_name);
qinsoon's avatar
qinsoon committed
127
128
129
130
131
132
133
134
                debug_assert!(
                    old.is_none(),
                    "ID already exists: {}, new name: {}, old name: {}",
                    my_id,
                    self.id_name_map.get(&my_id).unwrap(),
                    old.unwrap()
                );
            }
135
136
137
138
139
140
        };

        my_id
    }

    pub fn new_type_int(&mut self, id: MuID, len: c_int) {
qinsoon's avatar
qinsoon committed
141
142
143
        self.bundle
            .types
            .insert(id, Box::new(NodeType::TypeInt { id: id, len: len }));
144
145
146
    }

    pub fn new_type_float(&mut self, id: MuID) {
qinsoon's avatar
qinsoon committed
147
148
149
        self.bundle
            .types
            .insert(id, Box::new(NodeType::TypeFloat { id: id }));
150
151
152
    }

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

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

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

    pub fn new_type_struct(&mut self, id: MuID, fieldtys: Vec<MuID>) {
qinsoon's avatar
qinsoon committed
171
172
173
174
        self.bundle.types.insert(
            id,
            Box::new(NodeType::TypeStruct {
                id: id,
175
176
                fieldtys: fieldtys
            })
qinsoon's avatar
qinsoon committed
177
        );
178
179
180
    }

    pub fn new_type_hybrid(&mut self, id: MuID, fixedtys: Vec<MuID>, varty: MuID) {
qinsoon's avatar
qinsoon committed
181
182
183
184
185
        self.bundle.types.insert(
            id,
            Box::new(NodeType::TypeHybrid {
                id: id,
                fixedtys: fixedtys,
186
187
                varty: varty
            })
qinsoon's avatar
qinsoon committed
188
        );
189
190
191
    }

    pub fn new_type_array(&mut self, id: MuID, elemty: MuID, len: u64) {
qinsoon's avatar
qinsoon committed
192
193
194
195
196
        self.bundle.types.insert(
            id,
            Box::new(NodeType::TypeArray {
                id: id,
                elemty: elemty,
197
198
                len: len as usize
            })
qinsoon's avatar
qinsoon committed
199
        );
200
201
202
    }

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

    pub fn new_type_void(&mut self, id: MuID) {
qinsoon's avatar
qinsoon committed
214
215
216
        self.bundle
            .types
            .insert(id, Box::new(NodeType::TypeVoid { id: id }));
217
218
219
    }

    pub fn new_type_ref(&mut self, id: MuID, ty: MuID) {
qinsoon's avatar
qinsoon committed
220
221
222
        self.bundle
            .types
            .insert(id, Box::new(NodeType::TypeRef { id: id, ty: ty }));
223
224
225
    }

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

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

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

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

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

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

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

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

    pub fn new_funcsig(&mut self, id: MuID, paramtys: Vec<MuID>, rettys: Vec<MuID>) {
qinsoon's avatar
qinsoon committed
274
275
276
277
278
        self.bundle.sigs.insert(
            id,
            Box::new(NodeFuncSig {
                id: id,
                paramtys: paramtys,
279
280
                rettys: rettys
            })
qinsoon's avatar
qinsoon committed
281
        );
282
283
284
    }

    pub fn new_const_int(&mut self, id: MuID, ty: MuID, value: u64) {
qinsoon's avatar
qinsoon committed
285
286
287
288
289
        self.bundle.consts.insert(
            id,
            Box::new(NodeConst::ConstInt {
                id: id,
                ty: ty,
290
291
                value: value
            })
qinsoon's avatar
qinsoon committed
292
        );
293
294
295
    }

    pub fn new_const_int_ex(&mut self, id: MuID, ty: MuID, values: &[u64]) {
qinsoon's avatar
qinsoon committed
296
297
298
299
300
        self.bundle.consts.insert(
            id,
            Box::new(NodeConst::ConstIntEx {
                id: id,
                ty: ty,
301
302
                value: values.to_vec()
            })
qinsoon's avatar
qinsoon committed
303
        );
304
305
306
    }

    pub fn new_const_float(&mut self, id: MuID, ty: MuID, value: f32) {
qinsoon's avatar
qinsoon committed
307
308
309
310
311
        self.bundle.consts.insert(
            id,
            Box::new(NodeConst::ConstFloat {
                id: id,
                ty: ty,
312
313
                value: value
            })
qinsoon's avatar
qinsoon committed
314
        );
315
316
317
    }

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

    pub fn new_const_null(&mut self, id: MuID, ty: MuID) {
qinsoon's avatar
qinsoon committed
329
330
331
        self.bundle
            .consts
            .insert(id, Box::new(NodeConst::ConstNull { id: id, ty: ty }));
332
333
334
    }

    pub fn new_const_seq(&mut self, id: MuID, ty: MuID, elems: Vec<MuID>) {
qinsoon's avatar
qinsoon committed
335
336
337
338
339
        self.bundle.consts.insert(
            id,
            Box::new(NodeConst::ConstSeq {
                id: id,
                ty: ty,
340
341
                elems: elems
            })
qinsoon's avatar
qinsoon committed
342
        );
343
344
345
    }

    pub fn new_const_extern(&mut self, id: MuID, ty: MuID, symbol: String) {
qinsoon's avatar
qinsoon committed
346
347
348
349
350
        self.bundle.consts.insert(
            id,
            Box::new(NodeConst::ConstExtern {
                id: id,
                ty: ty,
351
352
                symbol: symbol
            })
qinsoon's avatar
qinsoon committed
353
        );
354
355
356
    }

    pub fn new_global_cell(&mut self, id: MuID, ty: MuID) {
qinsoon's avatar
qinsoon committed
357
358
359
        self.bundle
            .globals
            .insert(id, Box::new(NodeGlobalCell { id: id, ty: ty }));
360
361
362
    }

    pub fn new_func(&mut self, id: MuID, sig: MuID) {
qinsoon's avatar
qinsoon committed
363
364
365
        self.bundle
            .funcs
            .insert(id, Box::new(NodeFunc { id: id, sig: sig }));
366
367
368
369
370
371
372
    }

    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
373
374
375
376
377
        self.bundle.funcvers.insert(
            id,
            Box::new(NodeFuncVer {
                id: id,
                func: func,
378
379
                bbs: bbs
            })
qinsoon's avatar
qinsoon committed
380
381
382
383
384
385
386
387
388
        );
    }

    pub fn new_bb(
        &mut self,
        id: MuID,
        nor_param_ids: Vec<MuID>,
        nor_param_types: Vec<MuID>,
        exc_param_id: Option<MuID>,
389
        insts: Vec<MuID>
qinsoon's avatar
qinsoon committed
390
391
392
393
394
395
396
397
    ) {
        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,
398
399
                insts: insts
            })
qinsoon's avatar
qinsoon committed
400
        );
401
402
403
    }

    pub fn new_dest_clause(&mut self, id: MuID, dest: MuID, vars: Vec<MuID>) {
qinsoon's avatar
qinsoon committed
404
405
406
407
408
        self.bundle.dest_clauses.insert(
            id,
            Box::new(NodeDestClause {
                id: id,
                dest: dest,
409
410
                vars: vars
            })
qinsoon's avatar
qinsoon committed
411
        );
412
413
414
    }

    pub fn new_exc_clause(&mut self, id: MuID, nor: MuID, exc: MuID) {
qinsoon's avatar
qinsoon committed
415
416
417
418
419
        self.bundle.exc_clauses.insert(
            id,
            Box::new(NodeExcClause {
                id: id,
                nor: nor,
420
421
                exc: exc
            })
qinsoon's avatar
qinsoon committed
422
        );
423
424
425
    }

    pub fn new_keepalive_clause(&mut self, id: MuID, vars: Vec<MuID>) {
qinsoon's avatar
qinsoon committed
426
427
428
        self.bundle
            .ka_clauses
            .insert(id, Box::new(NodeKeepaliveClause { id: id, vars: vars }));
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
    }

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

447
448
449
450
451
    #[inline(always)]
    fn add_inst(&mut self, id: MuID, inst: NodeInst) {
        self.bundle.insts.insert(id, Box::new(inst));
    }

qinsoon's avatar
qinsoon committed
452
453
454
455
456
457
458
459
    pub fn new_binop(
        &mut self,
        id: MuID,
        result_id: MuID,
        optr: CMuBinOptr,
        ty: MuID,
        opnd1: MuID,
        opnd2: MuID,
460
        exc_clause: Option<MuID>
qinsoon's avatar
qinsoon committed
461
462
463
464
465
466
467
468
469
470
471
472
    ) {
        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,
473
474
                exc_clause: exc_clause
            }
qinsoon's avatar
qinsoon committed
475
476
477
478
479
480
481
482
483
484
485
486
487
        );
    }

    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,
488
        exc_clause: Option<MuID>
qinsoon's avatar
qinsoon committed
489
490
491
492
493
494
495
496
497
498
499
500
    ) {
        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,
501
502
                exc_clause: exc_clause
            }
qinsoon's avatar
qinsoon committed
503
504
505
506
507
508
509
510
511
512
        )
    }

    pub fn new_cmp(
        &mut self,
        id: MuID,
        result_id: MuID,
        optr: CMuCmpOptr,
        ty: MuID,
        opnd1: MuID,
513
        opnd2: MuID
qinsoon's avatar
qinsoon committed
514
515
516
517
518
519
520
521
522
    ) {
        self.add_inst(
            id,
            NodeInst::NodeCmp {
                id: id,
                result_id: result_id,
                optr: optr,
                ty: ty,
                opnd1: opnd1,
523
524
                opnd2: opnd2
            }
qinsoon's avatar
qinsoon committed
525
526
527
528
529
530
531
532
533
534
        );
    }

    pub fn new_conv(
        &mut self,
        id: MuID,
        result_id: MuID,
        optr: CMuConvOptr,
        from_ty: MuID,
        to_ty: MuID,
535
        opnd: MuID
qinsoon's avatar
qinsoon committed
536
537
538
539
540
541
542
543
544
    ) {
        self.add_inst(
            id,
            NodeInst::NodeConv {
                id: id,
                result_id: result_id,
                optr: optr,
                from_ty: from_ty,
                to_ty: to_ty,
545
546
                opnd: opnd
            }
qinsoon's avatar
qinsoon committed
547
548
549
550
551
552
553
554
555
556
557
        );
    }

    pub fn new_select(
        &mut self,
        id: MuID,
        result_id: MuID,
        cond_ty: MuID,
        opnd_ty: MuID,
        cond: MuID,
        if_true: MuID,
558
        if_false: MuID
qinsoon's avatar
qinsoon committed
559
560
561
562
563
564
565
566
567
568
    ) {
        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,
569
570
                if_false: if_false
            }
qinsoon's avatar
qinsoon committed
571
        );
572
573
574
    }

    pub fn new_branch(&mut self, id: MuID, dest: MuID) {
qinsoon's avatar
qinsoon committed
575
        self.add_inst(id, NodeInst::NodeBranch { id: id, dest: dest });
576
577
578
    }

    pub fn new_branch2(&mut self, id: MuID, cond: MuID, if_true: MuID, if_false: MuID) {
qinsoon's avatar
qinsoon committed
579
580
581
582
583
584
        self.add_inst(
            id,
            NodeInst::NodeBranch2 {
                id: id,
                cond: cond,
                if_true: if_true,
585
586
                if_false: if_false
            }
qinsoon's avatar
qinsoon committed
587
588
589
590
591
592
593
594
595
596
        );
    }

    pub fn new_switch(
        &mut self,
        id: MuID,
        opnd_ty: MuID,
        opnd: MuID,
        default_dest: MuID,
        cases: Vec<MuID>,
597
        dests: Vec<MuID>
qinsoon's avatar
qinsoon committed
598
599
600
601
602
603
604
605
606
    ) {
        self.add_inst(
            id,
            NodeInst::NodeSwitch {
                id: id,
                opnd_ty: opnd_ty,
                opnd: opnd,
                default_dest: default_dest,
                cases: cases,
607
608
                dests: dests
            }
qinsoon's avatar
qinsoon committed
609
610
611
612
613
614
615
616
617
618
619
        );
    }

    pub fn new_call(
        &mut self,
        id: MuID,
        result_ids: Vec<MuID>,
        sig: MuID,
        callee: MuID,
        args: Vec<MuID>,
        exc_clause: Option<MuID>,
620
        keepalive_clause: Option<MuID>
qinsoon's avatar
qinsoon committed
621
622
623
624
625
626
627
628
629
630
    ) {
        self.add_inst(
            id,
            NodeInst::NodeCall {
                id: id,
                result_ids: result_ids,
                sig: sig,
                callee: callee,
                args: args,
                exc_clause: exc_clause,
631
632
                keepalive_clause: keepalive_clause
            }
qinsoon's avatar
qinsoon committed
633
        );
634
635
636
    }

    pub fn new_tailcall(&mut self, id: MuID, sig: MuID, callee: MuID, args: Vec<MuID>) {
qinsoon's avatar
qinsoon committed
637
638
639
640
641
642
        self.add_inst(
            id,
            NodeInst::NodeTailCall {
                id: id,
                sig: sig,
                callee: callee,
643
644
                args: args
            }
qinsoon's avatar
qinsoon committed
645
        );
646
647
648
    }

    pub fn new_ret(&mut self, id: MuID, rvs: Vec<MuID>) {
qinsoon's avatar
qinsoon committed
649
        self.add_inst(id, NodeInst::NodeRet { id: id, rvs: rvs });
650
651
652
    }

    pub fn new_throw(&mut self, id: MuID, exc: MuID) {
qinsoon's avatar
qinsoon committed
653
654
655
656
657
658
659
660
661
        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,
662
        opnd: MuID
qinsoon's avatar
qinsoon committed
663
664
665
666
667
668
669
670
    ) {
        self.add_inst(
            id,
            NodeInst::NodeExtractValue {
                id: id,
                result_id: result_id,
                strty: strty,
                index: index,
671
672
                opnd: opnd
            }
qinsoon's avatar
qinsoon committed
673
674
675
676
677
678
679
680
681
682
        );
    }

    pub fn new_insertvalue(
        &mut self,
        id: MuID,
        result_id: MuID,
        strty: MuID,
        index: c_int,
        opnd: MuID,
683
        newval: MuID
qinsoon's avatar
qinsoon committed
684
685
686
687
688
689
690
691
692
    ) {
        self.add_inst(
            id,
            NodeInst::NodeInsertValue {
                id: id,
                result_id: result_id,
                strty: strty,
                index: index,
                opnd: opnd,
693
694
                newval: newval
            }
qinsoon's avatar
qinsoon committed
695
696
697
698
699
700
701
702
703
704
        );
    }

    pub fn new_extractelement(
        &mut self,
        id: MuID,
        result_id: MuID,
        seqty: MuID,
        indty: MuID,
        opnd: MuID,
705
        index: MuID
qinsoon's avatar
qinsoon committed
706
707
708
709
710
711
712
713
714
    ) {
        self.add_inst(
            id,
            NodeInst::NodeExtractElement {
                id: id,
                result_id: result_id,
                seqty: seqty,
                indty: indty,
                opnd: opnd,
715
716
                index: index
            }
qinsoon's avatar
qinsoon committed
717
718
719
720
721
722
723
724
725
726
727
        );
    }

    pub fn new_insertelement(
        &mut self,
        id: MuID,
        result_id: MuID,
        seqty: MuID,
        indty: MuID,
        opnd: MuID,
        index: MuID,
728
        newval: MuID
qinsoon's avatar
qinsoon committed
729
730
731
732
733
734
735
736
737
738
    ) {
        self.add_inst(
            id,
            NodeInst::NodeInsertElement {
                id: id,
                result_id: result_id,
                seqty: seqty,
                indty: indty,
                opnd: opnd,
                index: index,
739
740
                newval: newval
            }
qinsoon's avatar
qinsoon committed
741
742
743
744
745
746
747
748
749
750
751
        );
    }

    pub fn new_shufflevector(
        &mut self,
        id: MuID,
        result_id: MuID,
        vecty: MuID,
        maskty: MuID,
        vec1: MuID,
        vec2: MuID,
752
        mask: MuID
qinsoon's avatar
qinsoon committed
753
754
755
756
757
758
759
760
761
762
    ) {
        self.add_inst(
            id,
            NodeInst::NodeShuffleVector {
                id: id,
                result_id: result_id,
                vecty: vecty,
                maskty: maskty,
                vec1: vec1,
                vec2: vec2,
763
764
                mask: mask
            }
qinsoon's avatar
qinsoon committed
765
        );
766
767
768
    }

    pub fn new_new(&mut self, id: MuID, result_id: MuID, allocty: MuID, exc_clause: Option<MuID>) {
qinsoon's avatar
qinsoon committed
769
770
771
772
773
774
        self.add_inst(
            id,
            NodeInst::NodeNew {
                id: id,
                result_id: result_id,
                allocty: allocty,
775
776
                exc_clause: exc_clause
            }
qinsoon's avatar
qinsoon committed
777
778
779
780
781
782
783
784
785
786
        );
    }

    pub fn new_newhybrid(
        &mut self,
        id: MuID,
        result_id: MuID,
        allocty: MuID,
        lenty: MuID,
        length: MuID,
787
        exc_clause: Option<MuID>
qinsoon's avatar
qinsoon committed
788
789
790
791
792
793
794
795
796
    ) {
        self.add_inst(
            id,
            NodeInst::NodeNewHybrid {
                id: id,
                result_id: result_id,
                allocty: allocty,
                lenty: lenty,
                length: length,
797
798
                exc_clause: exc_clause
            }
qinsoon's avatar
qinsoon committed
799
800
801
802
803
804
805
806
        );
    }

    pub fn new_alloca(
        &mut self,
        id: MuID,
        result_id: MuID,
        allocty: MuID,
807
        exc_clause: Option<MuID>
qinsoon's avatar
qinsoon committed
808
809
810
811
812
813
814
    ) {
        self.add_inst(
            id,
            NodeInst::NodeAlloca {
                id: id,
                result_id: result_id,
                allocty: allocty,
815
816
                exc_clause: exc_clause
            }
qinsoon's avatar
qinsoon committed
817
818
819
820
821
822
823
824
825
826
        );
    }

    pub fn new_allocahybrid(
        &mut self,
        id: MuID,
        result_id: MuID,
        allocty: MuID,
        lenty: MuID,
        length: MuID,
827
        exc_clause: Option<MuID>
qinsoon's avatar
qinsoon committed
828
829
830
831
832
833
834
835
836
    ) {
        self.add_inst(
            id,
            NodeInst::NodeAllocaHybrid {
                id: id,
                result_id: result_id,
                allocty: allocty,
                lenty: lenty,
                length: length,
837
838
                exc_clause: exc_clause
            }
qinsoon's avatar
qinsoon committed
839
        );
840
841
842
    }

    pub fn new_getiref(&mut self, id: MuID, result_id: MuID, refty: MuID, opnd: MuID) {
qinsoon's avatar
qinsoon committed
843
844
845
846
847
848
        self.add_inst(
            id,
            NodeInst::NodeGetIRef {
                id: id,
                result_id: result_id,
                refty: refty,
849
850
                opnd: opnd
            }
qinsoon's avatar
qinsoon committed
851
852
853
854
855
856
857
858
859
860
        );
    }

    pub fn new_getfieldiref(
        &mut self,
        id: MuID,
        result_id: MuID,
        is_ptr: bool,
        refty: MuID,
        index: c_int,
861
        opnd: MuID
qinsoon's avatar
qinsoon committed
862
863
864
865
866
867
868
869
870
    ) {
        self.add_inst(
            id,
            NodeInst::NodeGetFieldIRef {
                id: id,
                result_id: result_id,
                is_ptr: is_ptr,
                refty: refty,
                index: index,
871
872
                opnd: opnd
            }
qinsoon's avatar
qinsoon committed
873
874
875
876
877
878
879
880
881
882
883
        );
    }

    pub fn new_getelemiref(
        &mut self,
        id: MuID,
        result_id: MuID,
        is_ptr: bool,
        refty: MuID,
        indty: MuID,
        opnd: MuID,
884
        index: MuID
qinsoon's avatar
qinsoon committed
885
886
887
888
889
890
891
892
893
894
    ) {
        self.add_inst(
            id,
            NodeInst::NodeGetElemIRef {
                id: id,
                result_id: result_id,
                is_ptr: is_ptr,
                refty: refty,
                indty: indty,
                opnd: opnd,
895
896
                index: index
            }
qinsoon's avatar
qinsoon committed
897
898
899
900
901
902
903
904
905
906
907
        );
    }

    pub fn new_shiftiref(
        &mut self,
        id: MuID,
        result_id: MuID,
        is_ptr: bool,
        refty: MuID,
        offty: MuID,
        opnd: MuID,
908
        offset: MuID
qinsoon's avatar
qinsoon committed
909
910
911
912
913
914
915
916
917
918
    ) {
        self.add_inst(
            id,
            NodeInst::NodeShiftIRef {
                id: id,
                result_id: result_id,
                is_ptr: is_ptr,
                refty: refty,
                offty: offty,
                opnd: opnd,
919
920
                offset: offset
            }
qinsoon's avatar
qinsoon committed
921
922
923
924
925
926
927
928
929
        );
    }

    pub fn new_getvarpartiref(
        &mut self,
        id: MuID,
        result_id: MuID,
        is_ptr: bool,
        refty: MuID,
930
        opnd: MuID
qinsoon's avatar
qinsoon committed
931
932
933
934
935
936
937
938
    ) {
        self.add_inst(
            id,
            NodeInst::NodeGetVarPartIRef {
                id: id,
                result_id: result_id,
                is_ptr: is_ptr,
                refty: refty,
939
940
                opnd: opnd
            }
qinsoon's avatar
qinsoon committed
941
942
943
944
945
946
947
948
949
950
951
        );
    }

    pub fn new_load(
        &mut self,
        id: MuID,
        result_id: MuID,
        is_ptr: bool,
        ord: CMuMemOrd,
        refty: MuID,
        loc: MuID,
952
        exc_clause: Option<MuID>
qinsoon's avatar
qinsoon committed
953
954
955
956
957
958
959
960
961
962
    ) {
        self.add_inst(
            id,
            NodeInst::NodeLoad {
                id: id,
                result_id: result_id,
                is_ptr: is_ptr,
                ord: ord,
                refty: refty,
                loc: loc,
963
964
                exc_clause: exc_clause
            }
qinsoon's avatar
qinsoon committed
965
966
967
968
969
970
971
972
973
974
975
        );
    }

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

    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,
1005
        exc_clause: Option<MuID>
qinsoon's avatar
qinsoon committed
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
    ) {
        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,
1021
1022
                exc_clause: exc_clause
            }
qinsoon's avatar
qinsoon committed
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
        );
    }

    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,
1036
        exc_clause: Option<MuID>
qinsoon's avatar
qinsoon committed
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
    ) {
        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,
1049
1050
                exc_clause: exc_clause
            }
qinsoon's avatar
qinsoon committed
1051
        );
1052
1053
1054
    }

    pub fn new_fence(&mut self, id: MuID, ord: CMuMemOrd) {
qinsoon's avatar
qinsoon committed
1055
1056
1057
1058
1059
1060
1061
1062
1063
        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>,
1064
        keepalive_clause: Option<MuID>
qinsoon's avatar
qinsoon committed
1065
1066
1067
1068
1069
1070
1071
1072
    ) {
        self.add_inst(
            id,
            NodeInst::NodeTrap {
                id: id,
                result_ids: result_ids,
                rettys: rettys,
                exc_clause: exc_clause,
1073
1074
                keepalive_clause: keepalive_clause
            }
qinsoon's avatar
qinsoon committed
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
        );
    }

    pub fn new_watchpoint(
        &mut self,
        id: MuID,
        wpid: CMuWPID,
        result_ids: Vec<MuID>,
        rettys: Vec<MuID>,
        dis: MuID,
        ena: MuID,
        exc: Option<MuID>,
1087
        keepalive_clause: Option<MuID>
qinsoon's avatar
qinsoon committed
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
    ) {
        self.add_inst(
            id,
            NodeInst::NodeWatchPoint {
                id: id,
                wpid: wpid as MuID,
                result_ids: result_ids,
                rettys: rettys,
                dis: dis,
                ena: ena,
                exc: exc,
1099
1100
                keepalive_clause: keepalive_clause
            }
qinsoon's avatar
qinsoon committed
1101
        );
1102
1103
    }

1104
    pub fn new_wpbranch(&mut self, id: MuID, wpid: CMuWPID, dis: MuID, ena: MuID) {
qinsoon's avatar
qinsoon committed
1105
1106
1107
1108
1109
1110
        self.add_inst(
            id,
            NodeInst::NodeWPBranch {
                id: id,
                wpid: wpid as MuID,
                dis: dis,
1111
1112
                ena: ena
            }
qinsoon's avatar
qinsoon committed
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
        );
    }

    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>,
1126
        keepalive_clause: Option<MuID>
qinsoon's avatar
qinsoon committed
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
    ) {
        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,
1139
1140
                keepalive_clause: keepalive_clause
            }
qinsoon's avatar
qinsoon committed
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
        );
    }

    pub fn new_newthread(
        &mut self,
        id: MuID,
        result_id: MuID,
        stack: MuID,
        threadlocal: Option<MuID>,
        new_stack_clause: MuID,
1151
        exc_clause: Option<MuID>
qinsoon's avatar
qinsoon committed
1152
1153
1154
1155
1156
1157
1158
1159
1160
    ) {
        self.add_inst(
            id,
            NodeInst::NodeNewThread {
                id: id,
                result_id: result_id,
                stack: stack,
                threadlocal: threadlocal,
                new_stack_clause: new_stack_clause,
1161
1162
                exc_clause: exc_clause
            }
qinsoon's avatar
qinsoon committed
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
        );
    }

    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>,
1174
        keepalive_clause: Option<MuID>
qinsoon's avatar
qinsoon committed
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
    ) {
        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,
1185
1186
                keepalive_clause: keepalive_clause
            }
qinsoon's avatar
qinsoon committed
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
        );
    }

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

1219
type IdPMap<T> = HashMap<MuID, P<T>>;
1220

Kunshan Wang's avatar
Kunshan Wang committed
1221
1222
1223
struct BundleLoader<'lb, 'lvm> {
    b: &'lb MuIRBuilder,
    vm: &'lvm VM,
1224
    id_name_map: HashMap<MuID, MuName>,
Kunshan Wang's avatar
Kunshan Wang committed
1225
1226
1227
    visited: HashSet<MuID>,
    built_types: IdPMap<MuType>,
    built_sigs: IdPMap<MuFuncSig>,
1228
1229
1230
1231
    built_constants: IdPMap<Value>,
    built_globals: IdPMap<Value>,
    built_funcs: IdBMap<MuFunction>,
    built_funcvers: IdBMap<MuFunctionVersion>,
1232
    struct_hybrid_id_tags: Vec<(MuID, MuName)>,
qinsoon's avatar
qinsoon committed
1233
1234
1235

    built_void: Option<P<MuType>>,
    built_refvoid: Option<P<MuType>>,
Kunshan Wang's avatar
Kunshan Wang committed
1236
    built_refi64: Option<P<MuType>>,
1237
    built_i1: Option<P<MuType>>,
1238
    built_i64: Option<P<MuType>>,
1239
1240
1241
1242
1243
    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
1244

1245
    built_funcref_of: IdPMap<MuType>,
1246
    built_ref_of: IdPMap<MuType>,
1247
    built_iref_of: IdPMap<MuType>,
qinsoon's avatar
qinsoon committed
1248
1249
    built_uptr_of: IdPMap<MuType>,

1250
    built_constint_of: HashMap<u64, P<Value>>
Kunshan Wang's avatar
Kunshan Wang committed
1251
}
1252

Kunshan Wang's avatar
Kunshan Wang committed
1253
fn load_bundle(b: &mut MuIRBuilder) {
1254
    let vm = b.get_vm();
1255

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

Kunshan Wang's avatar
Kunshan Wang committed
1258
1259
1260
    let mut bl = BundleLoader {
        b: b,
        vm: vm,
1261
        id_name_map: new_map,
Kunshan Wang's avatar
Kunshan Wang committed
1262
        visited: Default::default(),
Kunshan Wang's avatar
Kunshan Wang committed
1263
        built_types: Default::default(),
Kunshan Wang's avatar
Kunshan Wang committed
1264
        built_sigs: Default::default(),
1265
1266
        built_constants: Default::default(),
        built_globals: Default::default(),
1267
        built_funcs: Default::default(),
1268
        built_funcvers: Default::default(),
1269
        struct_hybrid_id_tags: Default::default(),
qinsoon's avatar
qinsoon committed
1270
1271
        built_void: Default::default(),
        built_refvoid: Default::default(),
Kunshan Wang's avatar
Kunshan Wang committed
1272
        built_refi64: Default::default(),
1273
        built_i1: Default::default(),
1274
        built_i64: Default::default(),
1275
1276
1277
1278
1279
        built_double: Default::default(),
        built_i52: Default::default(),
        built_i6: Default::default(),
        built_ref_void: Default::default(),
        built_tagref64: Default::default(),
1280
        built_funcref_of: Default::default(),
1281
        built_ref_of: Default::default(),
1282
        built_iref_of: Default::default(),
qinsoon's avatar
qinsoon committed
1283
        built_uptr_of: Default::default(),
1284
        built_constint_of: Default::default()
Kunshan Wang's avatar
Kunshan Wang committed
1285
1286
1287
    };

    bl.load_bundle();
1288
1289
}

Kunshan Wang's avatar
Kunshan Wang committed
1290
1291
1292
#[derive(Default)]
struct FuncCtxBuilder {
    ctx: FunctionContext,
1293
    tree_nodes: IdPMap<TreeNode>
1294
1295
}

qinsoon's avatar
qinsoon committed
1296
const DEFAULT_TRUE_PROB: f32 = 0.4f32;
1297

Kunshan Wang's avatar
Kunshan Wang committed
1298
1299
impl<'lb, 'lvm> BundleLoader<'lb, 'lvm> {
    fn load_bundle(&mut self) {
1300
1301
        self.ensure_names();
        self.build_toplevels();
1302
        self.add_everything_to_vm();
1303
1304
    }

qinsoon's avatar
qinsoon committed
1305
1306
1307
1308
1309
1310
1311
1312
1313
    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),
1314
            v: MuType_::Void
qinsoon's avatar
qinsoon committed
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
        });

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

qinsoon's avatar
qinsoon committed
1335
1336
1337
1338
1339
        trace!(
            "Ensure refvoid is defined: {} {:?}",
            id_refvoid,
            impl_refvoid
        );
qinsoon's avatar
qinsoon committed
1340
1341
1342
1343
1344
1345
1346

        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
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
    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),
1357
            v: MuType_::Int(64)
Kunshan Wang's avatar
Kunshan Wang committed
1358
1359