muirbuilder.rs 132 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::*;
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 127 128 129
        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
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: String) {
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

1248 1249 1250
struct BundleLoader<'lb, 'lvm> {
    b: &'lb MuIRBuilder,
    vm: &'lvm VM,
1251
    id_name_map: HashMap<MuID, MuName>,
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>>,
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>>,
qinsoon's avatar
qinsoon committed
1272

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

1278 1279
    built_constint_of: HashMap<u64, P<Value>>,
    current_sig: Option<P<MuFuncSig>>
1280
}
1281

1282
fn load_bundle(b: &mut MuIRBuilder) {
1283
    let vm = b.get_vm();
1284

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

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

    bl.load_bundle();
1319 1320
}

1321 1322 1323
#[derive(Default)]
struct FuncCtxBuilder {
    ctx: FunctionContext,
1324
    tree_nodes: IdPMap<TreeNode>
1325 1326
}

1327
const DEFAULT_TRUE_PROB: f32 = 0.4f32;
1328

1329 1330
impl<'lb, 'lvm> BundleLoader<'lb, 'lvm> {
    fn load_bundle(&mut self) {
1331 1332
        self.ensure_names();
        self.build_toplevels();
1333
        self.add_everything_to_vm();
1334 1335
    }

qinsoon's avatar
qinsoon committed
1336 1337 1338 1339 1340 1341 1342 1343 1344
    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),
1345
            v: MuType_::Void
qinsoon's avatar
qinsoon committed
1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365
        });

        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
1366 1367 1368 1369 1370
        trace!(
            "Ensure refvoid is defined: {} {:?}",
            id_refvoid,
            impl_refvoid
        );
qinsoon's avatar
qinsoon committed
1371 1372 1373 1374 1375 1376 1377

        self.built_types.insert(id_refvoid, impl_refvoid.clone());
        self.built_refvoid = Some(impl_refvoid.clone());

        impl_refvoid
    }

1378 1379 1380 1381 1382 1383 1384 1385 1386 1387
    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),
1388
            v: MuType_::Int(64)
1389 1390 1391 1392
        });

        let impl_ref = P(MuType {
            hdr: MuEntityHeader::unnamed(id_ref),
1393
            v: MuType_::Ref(impl_i64.clone())
1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406
        });

        trace!("Ensure i64 is defined: {} {:?}", id_i64, impl_i64);
        trace!("Ensure ref is defined: {} {:?}", id_ref, impl_ref);

        self.built_types.insert(id_i64, impl_i64);
        self.built_types.insert(id_ref, impl_ref.clone());

        self.built_refi64 = Some(impl_ref.clone());

        impl_ref
    }

1407
    fn ensure_i1(&mut self) -> P<MuType> {
1408 1409
        if let Some(ref impl_ty) = self.built_i1 {
            return impl_ty.clone();
1410 1411
        }

1412
        let id = self.vm.next_id();
1413

1414 1415
        let impl_ty = P(MuType {
            hdr: MuEntityHeader::unnamed(id),
1416
            v: MuType_::Int(1)
1417 1418
        });