muirbuilder.rs 129 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
}


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

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

41
    /// The "transient bundle" includes everything being built here.
42
    bundle: TransientBundle
43 44
}

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

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

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

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

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

87
    #[inline(always)]
88
    fn get_vm<'a, 'b>(&'a mut self) -> &'b VM {
89 90 91 92 93 94 95 96 97 98 99
        &self.get_mvm().vm
    }

    #[inline(always)]
    fn next_id(&mut self) -> MuID {
        self.get_vm().next_id()
    }

    fn deallocate(&mut self) {
        let c_struct = self.c_struct;
        let b_ptr = self as *mut MuIRBuilder;
qinsoon's avatar
qinsoon committed
100 101 102 103 104
        debug!(
            "Deallocating MuIRBuilder {:?} and CMuIRBuilder {:?}...",
            b_ptr,
            c_struct
        );
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
        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
131
        trace!("gen_sym({:?}) -> {}", name, my_id);
132 133

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

        my_id
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

qinsoon's avatar
qinsoon committed
480 481 482 483 484 485 486 487
    pub fn new_binop(
        &mut self,
        id: MuID,
        result_id: MuID,
        optr: CMuBinOptr,
        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: vec![],
                optr: optr,
                flags: 0,
                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 513 514 515
        );
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    built_void: Option<P<MuType>>,
    built_refvoid: Option<P<MuType>>,
1264
    built_refi64: Option<P<MuType>>,
1265
    built_i1: Option<P<MuType>>,
1266
    built_i64: Option<P<MuType>>,
1267 1268 1269 1270 1271
    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
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_funcref_of: Default::default(),
1310
        built_ref_of: Default::default(),
1311
        built_iref_of: Default::default(),
qinsoon's avatar
qinsoon committed
1312
        built_uptr_of: Default::default(),
1313 1314
        built_constint_of: Default::default(),
        current_sig: Default::default()
1315 1316 1317
    };

    bl.load_bundle();
1318 1319
}

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

1326
const DEFAULT_TRUE_PROB: f32 = 0.4f32;
1327

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

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

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

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

        impl_refvoid
    }

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

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

        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
    }

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

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

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

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