Research GitLab has introduced a user quota limitation. The new rule limits each user to have 50 Gb. The quota doesn't restrict group projects. If you have any concern with this, please talk to CECS Gitlab Admin at N110 (b) CSIT building.

muirbuilder.rs 48.6 KB
Newer Older
1
use super::common::*;
2
use ast::op::*;
3
use ast::inst::*;
4

5
pub struct MuIRBuilder {
6
    /// ref to MuVM
7
    mvm: *const MuVM,
8 9 10 11 12 13 14 15 16 17 18 19

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

    /// The "trantient bundle" includes everything being built here.
    bundle: TrantientBundle,
}

20
pub type IdBMap<T> = HashMap<MuID, Box<T>>;
21 22 23 24

/// A trantient bundle, i.e. the bundle being built, but not yet loaded into the MuVM.
#[derive(Default)]
pub struct TrantientBundle {
25 26 27 28 29 30 31 32 33 34 35 36
    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>,
    ka_clauses: IdBMap<NodeKeepaliveClause>,
37 38
}

39 40
impl MuIRBuilder {
    pub fn new(mvm: *const MuVM) -> Box<MuIRBuilder> {
41 42 43 44 45 46 47
        Box::new(MuIRBuilder {
            mvm: mvm,
            c_struct: ptr::null_mut(),
            id_name_map: Default::default(),
            bundle: Default::default(),
        })
    }
48

49
    #[inline(always)]
50 51 52
    fn get_mvm<'a, 'b>(&'a mut self) -> &'b MuVM {
        //self.mvm
        unsafe { & *self.mvm }
53 54 55
    }

    #[inline(always)]
56
    fn get_vm<'a, 'b>(&'a mut self) -> &'b VM {
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
        &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;
        debug!("Deallocating MuIRBuilder {:?} and CMuIRBuilder {:?}...", b_ptr, c_struct);
        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();

        debug!("gen_sym({:?}) -> {}", name, my_id);

        match name {
            None => {},
            Some(the_name) => {
                let old = self.id_name_map.insert(my_id, the_name);
                debug_assert!(old.is_none(), "ID already exists: {}, new name: {}, old name: {}",
                my_id, self.id_name_map.get(&my_id).unwrap(), old.unwrap());
            },
        };

        my_id
    }

    pub fn new_type_int(&mut self, id: MuID, len: c_int) {
        self.bundle.types.insert(id, Box::new(NodeType::TypeInt { id: id, len: len }));
    }

    pub fn new_type_float(&mut self, id: MuID) {
        panic!("Not implemented")
    }

    pub fn new_type_double(&mut self, id: MuID) {
        panic!("Not implemented")
    }

    pub fn new_type_uptr(&mut self, id: MuID, ty: MuID) {
        self.bundle.types.insert(id, Box::new(NodeType::TypeUPtr{ id: id,
            ty: ty }));
    }

    pub fn new_type_ufuncptr(&mut self, id: MuID, sig: MuID) {
Kunshan Wang's avatar
Kunshan Wang committed
127 128
        self.bundle.types.insert(id, Box::new(NodeType::TypeUFuncPtr{ id: id,
            sig: sig }));
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242
    }

    pub fn new_type_struct(&mut self, id: MuID, fieldtys: Vec<MuID>) {
        self.bundle.types.insert(id, Box::new(NodeType::TypeStruct { id: id,
            fieldtys: fieldtys }));
    }

    pub fn new_type_hybrid(&mut self, id: MuID, fixedtys: Vec<MuID>, varty: MuID) {
        panic!("Not implemented")
    }

    pub fn new_type_array(&mut self, id: MuID, elemty: MuID, len: u64) {
        panic!("Not implemented")
    }

    pub fn new_type_vector(&mut self, id: MuID, elemty: MuID, len: u64) {
        panic!("Not implemented")
    }

    pub fn new_type_void(&mut self, id: MuID) {
        panic!("Not implemented")
    }

    pub fn new_type_ref(&mut self, id: MuID, ty: MuID) {
        panic!("Not implemented")
    }

    pub fn new_type_iref(&mut self, id: MuID, ty: MuID) {
        panic!("Not implemented")
    }

    pub fn new_type_weakref(&mut self, id: MuID, ty: MuID) {
        panic!("Not implemented")
    }

    pub fn new_type_funcref(&mut self, id: MuID, sig: MuID) {
        panic!("Not implemented")
    }

    pub fn new_type_tagref64(&mut self, id: MuID) {
        panic!("Not implemented")
    }

    pub fn new_type_threadref(&mut self, id: MuID) {
        panic!("Not implemented")
    }

    pub fn new_type_stackref(&mut self, id: MuID) {
        panic!("Not implemented")
    }

    pub fn new_type_framecursorref(&mut self, id: MuID) {
        panic!("Not implemented")
    }

    pub fn new_type_irbuilderref(&mut self, id: MuID) {
        panic!("Not implemented")
    }

    pub fn new_funcsig(&mut self, id: MuID, paramtys: Vec<MuID>, rettys: Vec<MuID>) {
        self.bundle.sigs.insert(id, Box::new(NodeFuncSig { id: id,
            paramtys: paramtys, rettys: rettys }));
    }

    pub fn new_const_int(&mut self, id: MuID, ty: MuID, value: u64) {
        self.bundle.consts.insert(id, Box::new(NodeConst::ConstInt { id: id,
            ty: ty, value: value }));
    }

    pub fn new_const_int_ex(&mut self, id: MuID, ty: MuID, values: &[u64]) {
        panic!("Not implemented")
    }

    pub fn new_const_float(&mut self, id: MuID, ty: MuID, value: f32) {
        panic!("Not implemented")
    }

    pub fn new_const_double(&mut self, id: MuID, ty: MuID, value: f64) {
        panic!("Not implemented")
    }

    pub fn new_const_null(&mut self, id: MuID, ty: MuID) {
        panic!("Not implemented")
    }

    pub fn new_const_seq(&mut self, id: MuID, ty: MuID, elems: Vec<MuID>) {
        panic!("Not implemented")
    }

    pub fn new_const_extern(&mut self, id: MuID, ty: MuID, symbol: String) {
        panic!("Not implemented")
    }

    pub fn new_global_cell(&mut self, id: MuID, ty: MuID) {
        self.bundle.globals.insert(id, Box::new(NodeGlobalCell { id: id,
            ty: ty }));
    }

    pub fn new_func(&mut self, id: MuID, sig: MuID) {
        self.bundle.funcs.insert(id, Box::new(NodeFunc { id: id,
            sig: sig }));
    }

    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>) {
        self.bundle.funcvers.insert(id, Box::new(NodeFuncVer { id: id,
            func: func, bbs: bbs }));
    }

    pub fn new_bb(&mut self, id: MuID, nor_param_ids: Vec<MuID>, nor_param_types: Vec<MuID>, exc_param_id: Option<MuID>, insts: Vec<MuID>) {
        self.bundle.bbs.insert(id, Box::new(NodeBB { id: id,
243 244
            nor_param_ids: nor_param_ids, nor_param_types: nor_param_types,
            exc_param_id: exc_param_id, insts: insts }));
245 246 247
    }

    pub fn new_dest_clause(&mut self, id: MuID, dest: MuID, vars: Vec<MuID>) {
248 249
        self.bundle.dest_clauses.insert(id, Box::new(NodeDestClause { id: id,
            dest: dest, vars: vars }));
250 251 252
    }

    pub fn new_exc_clause(&mut self, id: MuID, nor: MuID, exc: MuID) {
253 254
        self.bundle.exc_clauses.insert(id, Box::new(NodeExcClause { id: id,
            nor: nor, exc: exc }));
255 256 257
    }

    pub fn new_keepalive_clause(&mut self, id: MuID, vars: Vec<MuID>) {
258 259
        self.bundle.ka_clauses.insert(id, Box::new(NodeKeepaliveClause { id: id,
            vars: vars }));
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277
    }

    pub fn new_csc_ret_with(&mut self, id: MuID, rettys: Vec<MuID>) {
        panic!("Not implemented")
    }

    pub fn new_csc_kill_old(&mut self, id: MuID) {
        panic!("Not implemented")
    }

    pub fn new_nsc_pass_values(&mut self, id: MuID, tys: Vec<MuID>, vars: Vec<MuID>) {
        panic!("Not implemented")
    }

    pub fn new_nsc_throw_exc(&mut self, id: MuID, exc: MuID) {
        panic!("Not implemented")
    }

278 279 280 281 282
    #[inline(always)]
    fn add_inst(&mut self, id: MuID, inst: NodeInst) {
        self.bundle.insts.insert(id, Box::new(inst));
    }

283
    pub fn new_binop(&mut self, id: MuID, result_id: MuID, optr: CMuBinOptr, ty: MuID, opnd1: MuID, opnd2: MuID, exc_clause: Option<MuID>) {
284 285
        self.add_inst(id, NodeInst::NodeBinOp {
            id: id, result_id: result_id, status_result_ids: vec![],
286
            optr: optr, flags: 0, ty: ty, opnd1: opnd1, opnd2: opnd2,
287 288
            exc_clause: exc_clause
        });
289 290 291 292 293 294 295
    }

    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, exc_clause: Option<MuID>) {
        panic!("Not implemented")
    }

    pub fn new_cmp(&mut self, id: MuID, result_id: MuID, optr: CMuCmpOptr, ty: MuID, opnd1: MuID, opnd2: MuID) {
296 297 298 299
        self.add_inst(id, NodeInst::NodeCmp {
            id: id, result_id: result_id,
            optr: optr, ty: ty, opnd1: opnd1, opnd2: opnd2
        });
300 301 302
    }

    pub fn new_conv(&mut self, id: MuID, result_id: MuID, optr: CMuConvOptr, from_ty: MuID, to_ty: MuID, opnd: MuID) {
303 304 305 306
        self.add_inst(id, NodeInst::NodeConv {
            id: id, result_id: result_id,
            optr: optr, from_ty: from_ty, to_ty: to_ty, opnd: opnd
        });
307 308 309
    }

    pub fn new_select(&mut self, id: MuID, result_id: MuID, cond_ty: MuID, opnd_ty: MuID, cond: MuID, if_true: MuID, if_false: MuID) {
310 311 312 313 314
        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, if_false: if_false
        });
315 316 317
    }

    pub fn new_branch(&mut self, id: MuID, dest: MuID) {
318 319 320
        self.add_inst(id, NodeInst::NodeBranch {
            id: id, dest: dest
        });
321 322 323
    }

    pub fn new_branch2(&mut self, id: MuID, cond: MuID, if_true: MuID, if_false: MuID) {
324 325 326
        self.add_inst(id, NodeInst::NodeBranch2 {
            id: id, cond: cond, if_true: if_true, if_false: if_false
        });
327 328 329
    }

    pub fn new_switch(&mut self, id: MuID, opnd_ty: MuID, opnd: MuID, default_dest: MuID, cases: Vec<MuID>, dests: Vec<MuID>) {
330 331 332 333
        self.add_inst(id, NodeInst::NodeSwitch {
            id: id, opnd_ty: opnd_ty, opnd: opnd, default_dest: default_dest,
            cases: cases, dests: dests
        });
334 335 336
    }

    pub fn new_call(&mut self, id: MuID, result_ids: Vec<MuID>, sig: MuID, callee: MuID, args: Vec<MuID>, exc_clause: Option<MuID>, keepalive_clause: Option<MuID>) {
337 338 339 340 341
        self.add_inst(id, NodeInst::NodeCall {
            id: id, result_ids: result_ids,
            sig: sig, callee: callee, args: args,
            exc_clause: exc_clause, keepalive_clause: keepalive_clause
        });
342 343 344
    }

    pub fn new_tailcall(&mut self, id: MuID, sig: MuID, callee: MuID, args: Vec<MuID>) {
345 346 347
        self.add_inst(id, NodeInst::NodeTailCall {
            id: id, sig: sig, callee: callee, args: args
        });
348 349 350
    }

    pub fn new_ret(&mut self, id: MuID, rvs: Vec<MuID>) {
351 352 353
        self.add_inst(id, NodeInst::NodeRet {
            id: id, rvs: rvs
        });
354 355 356
    }

    pub fn new_throw(&mut self, id: MuID, exc: MuID) {
357 358 359
        self.add_inst(id, NodeInst::NodeThrow {
            id: id, exc: exc
        });
360 361 362
    }

    pub fn new_extractvalue(&mut self, id: MuID, result_id: MuID, strty: MuID, index: c_int, opnd: MuID) {
363 364 365
        self.add_inst(id, NodeInst::NodeExtractValue {
            id: id, result_id: result_id, strty: strty, index: index, opnd: opnd
        });
366 367 368
    }

    pub fn new_insertvalue(&mut self, id: MuID, result_id: MuID, strty: MuID, index: c_int, opnd: MuID, newval: MuID) {
369 370 371
        self.add_inst(id, NodeInst::NodeInsertValue {
            id: id, result_id: result_id, strty: strty, index: index, opnd: opnd, newval: newval
        });
372 373 374
    }

    pub fn new_extractelement(&mut self, id: MuID, result_id: MuID, seqty: MuID, indty: MuID, opnd: MuID, index: MuID) {
375 376 377
        self.add_inst(id, NodeInst::NodeExtractElement {
            id: id, result_id: result_id, seqty: seqty, indty: indty, opnd: opnd, index: index
        });
378 379 380
    }

    pub fn new_insertelement(&mut self, id: MuID, result_id: MuID, seqty: MuID, indty: MuID, opnd: MuID, index: MuID, newval: MuID) {
381 382 383
        self.add_inst(id, NodeInst::NodeInsertElement {
            id: id, result_id: result_id, seqty: seqty, indty: indty, opnd: opnd, index: index, newval: newval
        });
384 385 386
    }

    pub fn new_shufflevector(&mut self, id: MuID, result_id: MuID, vecty: MuID, maskty: MuID, vec1: MuID, vec2: MuID, mask: MuID) {
387 388 389
        self.add_inst(id, NodeInst::NodeShuffleVector {
            id: id, result_id: result_id, vecty: vecty, maskty: maskty, vec1: vec1, vec2: vec2, mask: mask
        });
390 391 392
    }

    pub fn new_new(&mut self, id: MuID, result_id: MuID, allocty: MuID, exc_clause: Option<MuID>) {
393 394 395
        self.add_inst(id, NodeInst::NodeNew {
            id: id, result_id: result_id, allocty: allocty, exc_clause: exc_clause
        });
396 397 398
    }

    pub fn new_newhybrid(&mut self, id: MuID, result_id: MuID, allocty: MuID, lenty: MuID, length: MuID, exc_clause: Option<MuID>) {
399 400 401
        self.add_inst(id, NodeInst::NodeNewHybrid {
            id: id, result_id: result_id, allocty: allocty, lenty: lenty, length: length, exc_clause: exc_clause
        });
402 403 404
    }

    pub fn new_alloca(&mut self, id: MuID, result_id: MuID, allocty: MuID, exc_clause: Option<MuID>) {
405 406 407
        self.add_inst(id, NodeInst::NodeAlloca {
            id: id, result_id: result_id, allocty: allocty, exc_clause: exc_clause
        });
408 409 410
    }

    pub fn new_allocahybrid(&mut self, id: MuID, result_id: MuID, allocty: MuID, lenty: MuID, length: MuID, exc_clause: Option<MuID>) {
411 412 413
        self.add_inst(id, NodeInst::NodeAllocaHybrid {
            id: id, result_id: result_id, allocty: allocty, lenty: lenty, length: length, exc_clause: exc_clause
        });
414 415 416
    }

    pub fn new_getiref(&mut self, id: MuID, result_id: MuID, refty: MuID, opnd: MuID) {
417 418 419
        self.add_inst(id, NodeInst::NodeGetIRef {
            id: id, result_id: result_id, refty: refty, opnd: opnd
        });
420 421 422
    }

    pub fn new_getfieldiref(&mut self, id: MuID, result_id: MuID, is_ptr: bool, refty: MuID, index: c_int, opnd: MuID) {
423 424 425
        self.add_inst(id, NodeInst::NodeGetFieldIRef {
            id: id, result_id: result_id, is_ptr: is_ptr, refty: refty, index: index, opnd: opnd
        });
426 427 428
    }

    pub fn new_getelemiref(&mut self, id: MuID, result_id: MuID, is_ptr: bool, refty: MuID, indty: MuID, opnd: MuID, index: MuID) {
429 430 431
        self.add_inst(id, NodeInst::NodeGetElemIRef {
            id: id, result_id: result_id, is_ptr: is_ptr, refty: refty, indty: indty, opnd: opnd, index: index
        });
432 433 434
    }

    pub fn new_shiftiref(&mut self, id: MuID, result_id: MuID, is_ptr: bool, refty: MuID, offty: MuID, opnd: MuID, offset: MuID) {
435 436 437
        self.add_inst(id, NodeInst::NodeShiftIRef {
            id: id, result_id: result_id, is_ptr: is_ptr, refty: refty, offty: offty, opnd: opnd, offset: offset
        });
438 439 440
    }

    pub fn new_getvarpartiref(&mut self, id: MuID, result_id: MuID, is_ptr: bool, refty: MuID, opnd: MuID) {
441 442 443
        self.add_inst(id, NodeInst::NodeGetVarPartIRef {
            id: id, result_id: result_id, is_ptr: is_ptr, refty: refty, opnd: opnd
        });
444 445 446
    }

    pub fn new_load(&mut self, id: MuID, result_id: MuID, is_ptr: bool, ord: CMuMemOrd, refty: MuID, loc: MuID, exc_clause: Option<MuID>) {
447 448 449
        self.add_inst(id, NodeInst::NodeLoad {
            id: id, result_id: result_id, is_ptr: is_ptr, ord: ord, refty: refty, loc: loc, exc_clause: exc_clause
        });
450 451 452
    }

    pub fn new_store(&mut self, id: MuID, is_ptr: bool, ord: CMuMemOrd, refty: MuID, loc: MuID, newval: MuID, exc_clause: Option<MuID>) {
453 454 455
        self.add_inst(id, NodeInst::NodeStore {
            id: id, is_ptr: is_ptr, ord: ord, refty: refty, loc: loc, newval: newval, exc_clause: exc_clause
        });
456 457 458
    }

    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, exc_clause: Option<MuID>) {
459 460 461
        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, exc_clause: exc_clause
        });
462 463 464
    }

    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, exc_clause: Option<MuID>) {
465 466 467
        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, exc_clause: exc_clause
        });
468 469 470
    }

    pub fn new_fence(&mut self, id: MuID, ord: CMuMemOrd) {
471 472 473
        self.add_inst(id, NodeInst::NodeFence {
            id: id, ord: ord,
        });
474 475 476
    }

    pub fn new_trap(&mut self, id: MuID, result_ids: Vec<MuID>, rettys: Vec<MuID>, exc_clause: Option<MuID>, keepalive_clause: Option<MuID>) {
477 478 479
        self.add_inst(id, NodeInst::NodeTrap {
            id: id, result_ids: result_ids, rettys: rettys, exc_clause: exc_clause, keepalive_clause: keepalive_clause
        });
480 481 482
    }

    pub fn new_watchpoint(&mut self, id: MuID, wpid: CMuWPID, result_ids: Vec<MuID>, rettys: Vec<MuID>, dis: MuID, ena: MuID, exc: Option<MuID>, keepalive_clause: Option<MuID>) {
483 484 485
        self.add_inst(id, NodeInst::NodeWatchPoint {
            id: id, wpid: wpid as MuID, result_ids: result_ids, rettys: rettys, dis: dis, ena: ena, exc: exc, keepalive_clause: keepalive_clause
        });
486 487 488
    }

    pub fn new_wpbranch(&mut self, id: MuID, wpid: CMuWPID, dis: MuID, ena: MuID) {
489 490 491
        self.add_inst(id, NodeInst::NodeWPBranch {
            id: id, wpid: wpid as MuID, dis: dis, ena: ena
        });
492 493 494
    }

    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>, keepalive_clause: Option<MuID>) {
495 496 497
        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, keepalive_clause: keepalive_clause
        });
498 499 500
    }

    pub fn new_newthread(&mut self, id: MuID, result_id: MuID, stack: MuID, threadlocal: Option<MuID>, new_stack_clause: MuID, exc_clause: Option<MuID>) {
501 502 503
        self.add_inst(id, NodeInst::NodeNewThread {
            id: id, result_id: result_id, stack: stack, threadlocal: threadlocal, new_stack_clause: new_stack_clause, exc_clause: exc_clause
        });
504 505 506
    }

    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>, keepalive_clause: Option<MuID>) {
507 508 509
        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, keepalive_clause: keepalive_clause
        });
510 511 512
    }

    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>, keepalive_clause: Option<MuID>) {
513 514
        self.add_inst(id, NodeInst::NodeCommInst {
            id: id, result_ids: result_ids,
515
            opcode: opcode, flags: vec![], tys: tys, sigs: sigs, args: args,
516 517
            exc_clause: exc_clause, keepalive_clause: keepalive_clause
        });
518 519 520
    }
}

521
type IdPMap<T> = HashMap<MuID, P<T>>;
522

523 524 525
struct BundleLoader<'lb, 'lvm> {
    b: &'lb MuIRBuilder,
    vm: &'lvm VM,
526
    id_name_map: HashMap<MuID, MuName>,
527 528 529
    visited: HashSet<MuID>,
    built_types: IdPMap<MuType>,
    built_sigs: IdPMap<MuFuncSig>,
530 531 532 533
    built_constants: IdPMap<Value>,
    built_globals: IdPMap<Value>,
    built_funcs: IdBMap<MuFunction>,
    built_funcvers: IdBMap<MuFunctionVersion>,
534
    struct_id_tags: Vec<(MuID, MuName)>,
535
    built_refi64: Option<P<MuType>>,
536
    built_i1: Option<P<MuType>>,
537
    built_funcref_of: IdPMap<MuType>,
538
}
539

540
fn load_bundle(b: &mut MuIRBuilder) {
541
    let vm = b.get_vm();
542

543 544
    let new_map = b.id_name_map.drain().collect::<HashMap<_,_>>();

545 546 547
    let mut bl = BundleLoader {
        b: b,
        vm: vm,
548
        id_name_map: new_map,
549
        visited: Default::default(),
550
        built_types: Default::default(),
551
        built_sigs: Default::default(),
552 553
        built_constants: Default::default(),
        built_globals: Default::default(),
554
        built_funcs: Default::default(),
555
        built_funcvers: Default::default(),
556
        struct_id_tags: Default::default(),
557
        built_refi64: Default::default(),
558
        built_i1: Default::default(),
559
        built_funcref_of: Default::default(),
560 561 562
    };

    bl.load_bundle();
563 564
}

565 566 567 568
#[derive(Default)]
struct FuncCtxBuilder {
    ctx: FunctionContext,
    tree_nodes: IdPMap<TreeNode>,
569 570
}

571 572
const DEFAULT_TRUE_PROB: f32 = 0.6f32;

573 574
impl<'lb, 'lvm> BundleLoader<'lb, 'lvm> {
    fn load_bundle(&mut self) {
575 576
        self.ensure_names();
        self.build_toplevels();
577
        self.add_everything_to_vm();
578 579
    }

580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608
    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),
            v: MuType_::Int(64),
        });

        let impl_ref = P(MuType {
            hdr: MuEntityHeader::unnamed(id_ref),
            v: MuType_::Ref(impl_i64.clone()),
        });

        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
    }

609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627
    fn ensure_i1(&mut self) -> P<MuType> {
        if let Some(ref i1) = self.built_i1 {
            return i1.clone();
        }

        let id_i1 = self.vm.next_id();

        let impl_i1 = P(MuType {
            hdr: MuEntityHeader::unnamed(id_i1),
            v: MuType_::Int(1),
        });

        trace!("Ensure i1 is defined: {} {:?}", id_i1, impl_i1);

        self.built_types.insert(id_i1, impl_i1.clone());
        self.built_i1 = Some(impl_i1.clone());

        impl_i1
    }
628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649
    
    fn ensure_funcref(&mut self, sig_id: MuID) -> P<MuType> {
        if let Some(funcref) = self.built_funcref_of.get(&sig_id) {
            return funcref.clone();
        }

        let sig = self.built_sigs.get(&sig_id).unwrap().clone();

        let id_funcref = self.vm.next_id();

        let impl_funcref = P(MuType {
            hdr: MuEntityHeader::unnamed(id_funcref),
            v: MuType_::FuncRef(sig),
        });

        trace!("Ensure funcref of {} is defined: {} {:?}", sig_id, id_funcref, impl_funcref);

        self.built_types.insert(id_funcref, impl_funcref.clone());
        self.built_funcref_of.insert(sig_id, impl_funcref.clone());

        impl_funcref
    }
650

651
    fn name_from_id(id: MuID, hint: &str) -> String {
652
        format!("@uvm.unnamed.{}{}", hint, id)
653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673
    }

    fn ensure_name(&mut self, id: MuID, hint: &str) {
        self.id_name_map.entry(id).or_insert_with(|| {
            let name = BundleLoader::name_from_id(id, hint);
            trace!("Making name for ID {} : {}", id, name);
            name
        });
    }

    fn ensure_names(&mut self) {
        // Make sure structs have names because struct names are used to resolve cyclic
        // dependencies.
        for (id, ty) in &self.b.bundle.types {
            match **ty {
                NodeType::TypeStruct { id: _, fieldtys: _ } => { 
                    self.ensure_name(*id, "struct");
                },
                _ => {}
            }
        }
674 675 676 677 678 679 680 681

        for id in self.b.bundle.funcvers.keys() {
            self.ensure_name(*id, "funcver");
        }

        for id in self.b.bundle.bbs.keys() {
            self.ensure_name(*id, "funcver");
        }
682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699
    }

    fn get_name(&self, id: MuID) -> String {
        self.id_name_map.get(&id).unwrap().clone()
    }

    fn maybe_get_name(&self, id: MuID) -> Option<String> {
        self.id_name_map.get(&id).cloned()
    }

    fn make_mu_entity_header(&self, id: MuID) -> MuEntityHeader {
        match self.maybe_get_name(id) {
            None => MuEntityHeader::unnamed(id),
            Some(name) => MuEntityHeader::named(id, name),
        }
    }

    fn build_toplevels(&mut self) {
700
        for id in self.b.bundle.types.keys() {
701 702 703 704 705 706 707 708
            if !self.visited.contains(id) {
                self.build_type(*id)
            }
        }

        let struct_id_tags = self.struct_id_tags.drain(..).collect::<Vec<_>>();
        for (id, ref tag) in struct_id_tags {
            self.fill_struct(id, tag)
709
        }
Kunshan Wang's avatar
Kunshan Wang committed
710 711 712 713 714 715

        for id in self.b.bundle.sigs.keys() {
            if !self.visited.contains(id) {
                self.build_sig(*id)
            }
        }
716

717 718 719 720
        for id in self.b.bundle.consts.keys() {
            if !self.visited.contains(id) {
                self.build_const(*id)
            }
721
        }
722 723 724 725 726 727

        for id in self.b.bundle.funcs.keys() {
            if !self.visited.contains(id) {
                self.build_func(*id)
            }
        }
728 729 730 731

        for id in self.b.bundle.funcvers.keys() {
            self.build_funcver(*id)
        }
732
    }
733

734 735 736 737
    fn build_type(&mut self, id: MuID) {
        self.visited.insert(id);

        let ty = self.b.bundle.types.get(&id).unwrap();
738

739 740
        trace!("Building type {} {:?}", id, ty);

741 742 743
        let hdr = self.make_mu_entity_header(id);

        let impl_ty_ = match **ty {
744 745
            NodeType::TypeInt { id: _, len: len } => {
                MuType_::Int(len as usize)
746
            },
747
            NodeType::TypeUPtr { id: _, ty: toty } => {
748
                let toty_i = self.ensure_type_rec(toty);
749 750
                MuType_::UPtr(toty_i)
            },
Kunshan Wang's avatar
Kunshan Wang committed
751 752 753 754
            NodeType::TypeUFuncPtr { id: _, sig: sig } => {
                let sig_i = self.ensure_sig_rec(sig);
                MuType_::UFuncPtr(sig_i)
            },
755
            NodeType::TypeStruct { id: _, fieldtys: _ } => { 
756
                let tag = self.get_name(id);
757 758
                self.struct_id_tags.push((id, tag.clone()));
                MuType_::Struct(tag)
759 760
            },
            ref t => panic!("{:?} not implemented", t),
761 762 763
        };

        let impl_ty = MuType { hdr: hdr, v: impl_ty_ };
764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779

        trace!("Type built: {} {:?}", id, impl_ty);

        self.built_types.insert(id, P(impl_ty));
    }

    fn ensure_type_rec(&mut self, id: MuID) -> P<MuType> {
        if self.b.bundle.types.contains_key(&id) {
            if self.visited.contains(&id) {
                match self.built_types.get(&id) {
                    Some(t) => t.clone(),
                    None => panic!("Cyclic types found. id: {}", id)
                }
            } else {
                self.build_type(id);
                self.built_types.get(&id).unwrap().clone()
780 781
            }
        } else {
782
            self.vm.get_type(id)
783
        }
784
    }
785

786 787 788 789 790 791 792
    fn get_built_type(&self, id: MuID) -> P<MuType> {
        match self.built_types.get(&id) {
            Some(t) => t.clone(),
            None => self.vm.get_type(id)
        }
    }

793 794
    fn fill_struct(&mut self, id: MuID, tag: &MuName) {
        let ty = self.b.bundle.types.get(&id).unwrap();
795

796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815
        trace!("Filling struct {} {:?}", id, ty);

        match **ty {
            NodeType::TypeStruct { id: _, fieldtys: ref fieldtys } => { 
                let fieldtys_impl = fieldtys.iter().map(|fid| {
                    self.ensure_type_rec(*fid)
                }).collect::<Vec<_>>();

                let struct_ty_ = StructType_::new(fieldtys_impl);

                match STRUCT_TAG_MAP.read().unwrap().get(tag) {
                    Some(old_struct_ty_) => {
                        if struct_ty_ != *old_struct_ty_ {
                            panic!("trying to insert {:?} as {}, while the old struct is defined as {:?}",
                                   struct_ty_, tag, old_struct_ty_)
                        }
                    },
                    None => {}
                }
                STRUCT_TAG_MAP.write().unwrap().insert(tag.clone(), struct_ty_);
816

817
                trace!("Struct {} filled: {:?}", id,
818
                       STRUCT_TAG_MAP.read().unwrap().get(tag));
819 820 821 822
            },
            ref t => panic!("{} {:?} should be a Struct type", id, ty),
        }
    }
Kunshan Wang's avatar
Kunshan Wang committed
823 824 825 826 827

    fn build_sig(&mut self, id: MuID) {
        self.visited.insert(id);

        let sig = self.b.bundle.sigs.get(&id).unwrap();
828

Kunshan Wang's avatar
Kunshan Wang committed
829 830
        trace!("Building function signature {} {:?}", id, sig);

831 832
        let hdr = self.make_mu_entity_header(id);

Kunshan Wang's avatar
Kunshan Wang committed
833
        let impl_sig = MuFuncSig{
834
            hdr: hdr,
Kunshan Wang's avatar
Kunshan Wang committed
835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858
            ret_tys: sig.rettys.iter().map(|i| self.ensure_type_rec(*i)).collect::<Vec<_>>(),
            arg_tys: sig.paramtys.iter().map(|i| self.ensure_type_rec(*i)).collect::<Vec<_>>(),
        };

        trace!("Function signature built: {} {:?}", id, impl_sig);

        self.built_sigs.insert(id, P(impl_sig));
    }

    fn ensure_sig_rec(&mut self, id: MuID) -> P<MuFuncSig> {
        if self.b.bundle.sigs.contains_key(&id) {
            if self.visited.contains(&id) {
                match self.built_sigs.get(&id) {
                    Some(t) => t.clone(),
                    None => panic!("Cyclic signature found. id: {}", id)
                }
            } else {
                self.build_sig(id);
                self.built_sigs.get(&id).unwrap().clone()
            }
        } else {
            self.vm.get_func_sig(id)
        }
    }
859 860 861 862 863

    fn build_const(&mut self, id: MuID) {
        self.visited.insert(id);

        let con = self.b.bundle.consts.get(&id).unwrap();
864

865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885
        trace!("Building constant {} {:?}", id, con);

        let hdr = self.make_mu_entity_header(id);

        let (impl_con, impl_ty) = match **con {
            NodeConst::ConstInt { id: _, ty: ty, value: value } => {
                let t = self.ensure_type_rec(ty);
                let c = Constant::Int(value);
                (c, t)
            },
            ref c => panic!("{:?} not implemented", c),
        };

        let impl_val = Value {
            hdr: hdr,
            ty: impl_ty,
            v: Value_::Constant(impl_con),
        };

        trace!("Constant built: {} {:?}", id, impl_val);

886
        self.built_constants.insert(id, P(impl_val));
887
    }
888 889 890 891 892 893 894 895 896 897 898 899

    fn build_func(&mut self, id: MuID) {
        self.visited.insert(id);

        let fun = self.b.bundle.funcs.get(&id).unwrap();

        trace!("Building function {} {:?}", id, fun);

        let hdr = self.make_mu_entity_header(id);
        let impl_sig = self.ensure_sig_rec(fun.sig);

        let impl_fun = MuFunction {
900
            hdr: hdr.clone(),
901 902 903 904 905 906 907
            sig: impl_sig,
            cur_ver: None,
            all_vers: Default::default(),
        };

        trace!("Function built: {} {:?}", id, impl_fun);

908
        self.built_funcs.insert(id, Box::new(impl_fun));
909 910 911 912 913 914 915 916 917 918 919

        let impl_ty = self.ensure_funcref(fun.sig);

        let impl_val = Value {
            hdr: hdr,
            ty: impl_ty,
            v: Value_::Constant(Constant::FuncRef(id)),
        };

        trace!("Function value built: {} {:?}", id, impl_val);

920
        self.built_constants.insert(id, P(impl_val));
921
    }
922

923 924 925 926 927 928 929 930 931
    fn get_sig_for_func(&mut self, id: MuID) -> P<MuFuncSig> {
        if let Some(impl_func) = self.built_funcs.get(&id) {
            impl_func.sig.clone()
        } else {
            self.vm.get_func_sig_for_func(id)
        }
    }


932 933
    fn build_funcver(&mut self, id: MuID) {
        let fv = self.b.bundle.funcvers.get(&id).unwrap();
934

935 936 937
        trace!("Building function version {} {:?}", id, fv);

        let hdr = self.make_mu_entity_header(id);
938 939
        let func_id = fv.func;
        let impl_sig = self.get_sig_for_func(func_id);
940

941
        let mut fcb: FuncCtxBuilder = Default::default();
942 943

        let blocks = fv.bbs.iter().map(|bbid| {
944
            let block = self.build_block(&mut fcb, *bbid);
945 946 947 948 949 950 951 952 953 954 955
            (*bbid, block)
        }).collect::<HashMap<MuID, Block>>();

        let entry_id = *fv.bbs.first().unwrap();
        let ctn = FunctionContent {
            entry: entry_id,
            blocks: blocks,
        };

        let impl_fv = MuFunctionVersion {
            hdr: hdr,
956
            func_id: func_id,
957 958
            sig: impl_sig,
            content: Some(ctn),
959
            context: fcb.ctx,
960 961 962 963 964
            block_trace: None,
        };

        trace!("Function version built {} {:?}", id, impl_fv);

965
        self.built_funcvers.insert(id, Box::new(impl_fv));
966 967 968 969 970
    }

    /// Copied from ast::ir::*. That was implemented for the previous API which implies mutability.
    /// When we migrate later, we can assume the AST is almost fully immutable, and can be
    /// constructed in a functional recursive-descendent style.
971
    fn new_ssa(&self, fcb: &mut FuncCtxBuilder, id: MuID, ty: P<MuType>) -> P<TreeNode> {
972 973 974 975 976 977 978
        let hdr = self.make_mu_entity_header(id);
        let val = P(Value{
            hdr: hdr,
            ty: ty,
            v: Value_::SSAVar(id)
        });

979
        fcb.ctx.values.insert(id, SSAVarEntry::new(val.clone()));
980

981
        let tn = P(TreeNode {
982 983
            op: pick_op_code_for_ssa(&val.ty),
            v: TreeNode_::Value(val)
984 985 986 987 988 989 990 991 992 993 994 995 996
        });

        fcb.tree_nodes.insert(id, tn.clone());

        tn
    }

    pub fn new_inst(&self, v: Instruction) -> Box<TreeNode> {
        Box::new(TreeNode{
            op: pick_op_code_for_inst(&v),
            v: TreeNode_::Instruction(v),
        })
    }
997

998 999 1000 1001
    pub fn new_global(&self, v: P<Value>) -> P<TreeNode> {
        P(TreeNode{
            op: pick_op_code_for_value(&v.ty),
            v: TreeNode_::Value(v)
1002 1003 1004
        })
    }

1005 1006 1007
    fn get_treenode(&self, fcb: &FuncCtxBuilder, id: MuID) -> P<TreeNode> {
        if let Some(tn) = fcb.tree_nodes.get(&id) {
            tn.clone()
1008
        } else if let Some(v) = self.built_constants.get(&id) {
1009 1010 1011 1012 1013 1014 1015
            self.new_global(v.clone())
        } else {
            panic!("Operand {} is neither a local var or a global var", id)
        }
    }

    fn build_block(&mut self, fcb: &mut FuncCtxBuilder, id: MuID) -> Block {
1016 1017 1018 1019
        let bb = self.b.bundle.bbs.get(&id).unwrap();

        trace!("Building basic block {} {:?}", id, bb);

1020 1021
        let nor_ids = &bb.nor_param_ids;
        let nor_tys = &bb.nor_param_types;
1022 1023 1024

        let args = nor_ids.iter().zip(nor_tys).map(|(arg_id, arg_ty_id)| {
            let arg_ty = self.get_built_type(*arg_ty_id);
1025
            self.new_ssa(fcb, *arg_id, arg_ty).clone_value()
1026 1027
        }).collect::<Vec<_>>();

1028
        let exn_arg = bb.exc_param_id.map(|arg_id| {
1029 1030
            let arg_ty = self.ensure_refi64();
            self.new_ssa(fcb, arg_id, arg_ty).clone_value()
1031 1032 1033 1034
        });

        let hdr = self.make_mu_entity_header(id);

1035 1036
        let body = self.build_block_content(fcb, &bb.insts);

1037 1038 1039
        let ctn = BlockContent {
            args: args,
            exn_arg: exn_arg,
1040
            body: body,
1041 1042 1043 1044 1045 1046 1047 1048 1049
            keepalives: None,
        };

        Block {
            hdr: hdr,
            content: Some(ctn),
            control_flow: Default::default(),
        }
    }
1050

1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063
    fn build_block_content(&mut self, fcb: &mut FuncCtxBuilder, insts: &Vec<MuID>) -> Vec<Box<TreeNode>> {
        insts.iter().map(|iid| self.build_inst(fcb, *iid)).collect::<Vec<_>>()
    }

    fn build_inst(&mut self, fcb: &mut FuncCtxBuilder, id: MuID) -> Box<TreeNode> {
        let inst = self.b.bundle.insts.get(&id).unwrap();

        trace!("Building instruction {} {:?}", id, inst);

        let hdr = self.make_mu_entity_header(id);

        let impl_inst = match **inst {
            NodeInst::NodeBinOp {
1064 1065
                id: _, result_id, status_result_ids: _,
                optr, flags: _, ty, opnd1, opnd2,
1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093
                exc_clause: _
            } => {
                let impl_optr = match optr {
                    CMU_BINOP_ADD  => BinOp::Add,
                    CMU_BINOP_SUB  => BinOp::Sub,
                    CMU_BINOP_MUL  => BinOp::Mul,
                    CMU_BINOP_SDIV => BinOp::Sdiv,
                    CMU_BINOP_SREM => BinOp::Srem,
                    CMU_BINOP_UDIV => BinOp::Udiv,
                    CMU_BINOP_UREM => BinOp::Urem,
                    CMU_BINOP_SHL  => BinOp::Shl,
                    CMU_BINOP_LSHR => BinOp::Lshr,
                    CMU_BINOP_ASHR => BinOp::Ashr,
                    CMU_BINOP_AND  => BinOp::And,
                    CMU_BINOP_OR   => BinOp::Or,
                    CMU_BINOP_XOR  => BinOp::Xor,
                    CMU_BINOP_FADD => BinOp::FAdd,
                    CMU_BINOP_FSUB => BinOp::FSub,
                    CMU_BINOP_FMUL => BinOp::FMul,
                    CMU_BINOP_FDIV => BinOp::FDiv,
                    CMU_BINOP_FREM => BinOp::FRem,
                    _ => panic!("Illegal binary operator {}", optr)
                };
                let impl_ty = self.get_built_type(ty);
                let impl_opnd1 = self.get_treenode(fcb, opnd1);
                let impl_opnd2 = self.get_treenode(fcb, opnd2);
                let impl_rv = self.new_ssa(fcb, result_id, impl_ty);
                let impl_rv_value = impl_rv.clone_value();
1094

1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140
                Instruction {
                    hdr: hdr,
                    value: Some(vec![impl_rv_value]),
                    ops: RwLock::new(vec![impl_opnd1, impl_opnd2]),
                    v: Instruction_::BinOp(impl_optr, 0, 1),
                }
            },
            NodeInst::NodeCmp {
                id: _, result_id, optr, ty, opnd1, opnd2
            } => {
                let impl_optr = match optr {
                    CMU_CMP_EQ  => CmpOp::EQ,
                    CMU_CMP_NE  => CmpOp::NE,
                    CMU_CMP_SGE    => CmpOp::SGE,
                    CMU_CMP_SGT    => CmpOp::SGT,
                    CMU_CMP_SLE    => CmpOp::SLE,
                    CMU_CMP_SLT    => CmpOp::SLT,
                    CMU_CMP_UGE    => CmpOp::UGE,
                    CMU_CMP_UGT    => CmpOp::UGT,
                    CMU_CMP_ULE    => CmpOp::ULE,
                    CMU_CMP_ULT    => CmpOp::ULT,
                    CMU_CMP_FFALSE => CmpOp::FFALSE,
                    CMU_CMP_FTRUE  => CmpOp::FTRUE,
                    CMU_CMP_FUNO   => CmpOp::FUNO,
                    CMU_CMP_FUEQ   => CmpOp::FUEQ,
                    CMU_CMP_FUNE   => CmpOp::FUNE,
                    CMU_CMP_FUGT   => CmpOp::FUGT,
                    CMU_CMP_FUGE   => CmpOp::FUGE,
                    CMU_CMP_FULT   => CmpOp::FULT,
                    CMU_CMP_FULE   => CmpOp::FULE,
                    CMU_CMP_FORD   => CmpOp::FORD,
                    CMU_CMP_FOEQ   => CmpOp::FOEQ,
                    CMU_CMP_FONE   => CmpOp::FONE,
                    CMU_CMP_FOGT   => CmpOp::FOGT,
                    CMU_CMP_FOGE   => CmpOp::FOGE,
                    CMU_CMP_FOLT   => CmpOp::FOLT,
                    CMU_CMP_FOLE   => CmpOp::FOLE,
                    _ => panic!("Illegal comparing operator {}", optr)
                };
                // NOTE: vectors not implemented. Otherwise the result would be a vector of
                // int<1>
                let impl_i1 = self.ensure_i1();
                let impl_opnd1 = self.get_treenode(fcb, opnd1);
                let impl_opnd2 = self.get_treenode(fcb, opnd2);
                let impl_rv = self.new_ssa(fcb, result_id, impl_i1);
                let impl_rv_value = impl_rv.clone_value();
1141

1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152
                Instruction {
                    hdr: hdr,
                    value: Some(vec![impl_rv_value]),
                    ops: RwLock::new(vec![impl_opnd1, impl_opnd2]),
                    v: Instruction_::CmpOp(impl_optr, 0, 1),
                }
            },
            NodeInst::NodeConv {
                id: _, result_id, optr, from_ty, to_ty, opnd
            } => {
                panic!("Conversion not implemented")
1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178
                    // let impl_optr = match optr {
                    //     CMU_CONV_TRUNC   => ComvOp::TRUNC,
                    //     CMU_CONV_ZEXT    => ComvOp::ZEXT,
                    //     CMU_CONV_SEXT    => ComvOp::SEXT,
                    //     CMU_CONV_FPTRUNC => ComvOp::FPTRUNC,
                    //     CMU_CONV_FPEXT   => ComvOp::FPEXT,
                    //     CMU_CONV_FPTOUI  => ComvOp::FPTOUI,
                    //     CMU_CONV_FPTOSI  => ComvOp::FPTOSI,
                    //     CMU_CONV_UITOFP  => ComvOp::UITOFP,
                    //     CMU_CONV_SITOFP  => ComvOp::SITOFP,
                    //     CMU_CONV_BITCAST => ComvOp::BITCAST,
                    //     CMU_CONV_REFCAST => ComvOp::REFCAST,
                    //     CMU_CONV_PTRCAST => ComvOp::PTRCAST,
                    //     _ => panic!("Illegal conversion operator {}", optr)
                    // };
                    // let impl_to_ty = self.get_built_type(to_ty);
                    // let impl_opnd = self.get_treenode(fcb, opnd);
                    // let impl_rv = self.new_ssa(fcb, result_id, impl_to_ty);
                    // let impl_rv_value = impl_rv.clone_value();

                    // Instruction {
                    //     hdr: hdr,
                    //     value: Some(vec![impl_rv_value]),
                    //     ops: RwLock::new(vec![impl_opnd]),
                    //     v: Instruction_::ComvOp(impl_optr, 0),
                    // }
1179 1180 1181
            },
            NodeInst::NodeBranch { id: _, dest } => { 
                let (impl_dest, ops) = self.build_destination(fcb, dest, 0, &[]);
1182

1183 1184 1185 1186 1187
                Instruction {
                    hdr: hdr,
                    value: None,
                    ops: RwLock::new(ops),
                    v: Instruction_::Branch1(impl_dest),
1188
                }
1189
            },
1190 1191 1192 1193 1194 1195
            NodeInst::NodeBranch2 { id: _, cond, if_true, if_false } => { 
                let mut ops: Vec<P<TreeNode>> = Vec::new();

                let impl_cond = self.get_treenode(fcb, cond);
                ops.push(impl_cond);

1196 1197
                let (impl_dest_true, mut ops_true) = self.build_destination(fcb, if_true, ops.len(), &[]);
                ops.append(&mut ops_true);
1198

1199 1200
                let (impl_dest_false, mut ops_false) = self.build_destination(fcb, if_false, ops.len(), &[]);
                ops.append(&mut ops_false);
1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212

                Instruction {
                    hdr: hdr,
                    value: None,
                    ops: RwLock::new(ops),
                    v: Instruction_::Branch2 {
                        cond: 0,
                        true_dest: impl_dest_true,
                        false_dest: impl_dest_false,
                        true_prob: DEFAULT_TRUE_PROB,
                    },
                }
1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316
            },
            NodeInst::NodeSwitch {
                id: _, opnd_ty, opnd, default_dest, ref cases, ref dests
            } => {
                let mut ops: Vec<P<TreeNode>> = Vec::new();

                let impl_cond = self.get_treenode(fcb, opnd);
                ops.push(impl_cond);

                let (impl_dest_def, mut ops_def) = self.build_destination(fcb, default_dest, ops.len(), &[]);
                ops.append(&mut ops_def);

                let impl_branches = cases.iter().zip(dests).map(|(cid, did)| {
                    let case_opindex = ops.len();
                    let impl_case = self.get_treenode(fcb, *cid);
                    ops.push(impl_case);

                    let (impl_dest, mut ops_dest) = self.build_destination(fcb, *did, ops.len(), &[]);
                    ops.append(&mut ops_dest);

                    (case_opindex, impl_dest)
                }).collect::<Vec<_>>();

                Instruction {
                    hdr: hdr,
                    value: None,
                    ops: RwLock::new(ops),
                    v: Instruction_::Switch {
                        cond: 0,
                        default: impl_dest_def,
                        branches: impl_branches,
                    },
                }
            },
            NodeInst::NodeCall {
                id: _, ref result_ids, sig, callee, ref args, exc_clause, keepalive_clause
            } => {
                let mut ops: Vec<P<TreeNode>> = Vec::new();

                let impl_func = self.get_treenode(fcb, callee);
                ops.push(impl_func);

                let mut impl_args = args.iter().map(|argid| {
                    self.get_treenode(fcb, *argid)
                }).collect::<Vec<_>>();
                ops.append(&mut impl_args);

                let args_opindexes = (1..(args.len()+1)).collect::<Vec<_>>();

                let call_data = CallData {
                    func: 0,
                    args: args_opindexes,
                    convention: CallConvention::Mu,
                };

                let signode = self.b.bundle.sigs.get(&sig).unwrap();
                let rettys_ids = &signode.rettys;

                let rvs = result_ids.iter().zip(rettys_ids).map(|(rvid, rvty)| {
                    let impl_rvty = self.get_built_type(*rvty);
                    self.new_ssa(fcb, *rvid, impl_rvty).clone_value()
                }).collect::<Vec<_>>();

                if let Some(ecid) = exc_clause {
                    // terminating inst
                    let ecnode = self.b.bundle.exc_clauses.get(&ecid).unwrap();
                    
                    let (impl_normal_dest, mut nor_ops) = {
                        self.build_destination(fcb, ecnode.nor, ops.len(), result_ids.as_slice())
                    };
                    ops.append(&mut nor_ops);

                    let (impl_exn_dest, mut exc_ops) = {
                        self.build_destination(fcb, ecnode.exc, ops.len(), &[])
                    };
                    ops.append(&mut exc_ops);
                   
                    let resumption_data = ResumptionData {
                        normal_dest: impl_normal_dest,
                        exn_dest: impl_exn_dest,
                    };

                    Instruction {
                        hdr: hdr,
                        value: Some(rvs),
                        ops: RwLock::new(ops),
                        v: Instruction_::Call{
                            data: call_data,
                            resume: resumption_data,
                        },
                    }
                } else {
                    // non-terminating inst
                    Instruction {
                        hdr: hdr,
                        value: Some(rvs),
                        ops: RwLock::new(ops),
                        v: Instruction_::ExprCall {
                            data: call_data,
                            is_abort: false,
                        },
                    }
                }
            },
1317 1318 1319 1320 1321 1322 1323 1324 1325 1326
            NodeInst::NodeRet { id: _, ref rvs } => {
                let ops = rvs.iter().map(|rvid| self.get_treenode(fcb, *rvid)).collect::<Vec<_>>();
                let op_indexes = (0..(ops.len())).collect::<Vec<_>>();

                Instruction {
                    hdr: hdr,
                    value: None,
                    ops: RwLock::new(ops),
                    v: Instruction_::Return(op_indexes),
                }
1327
            },
1328 1329 1330 1331 1332 1333 1334
            ref i => panic!("{:?} not implemented", i),
        };

        trace!("Instruction built {} {:?}", id, impl_inst);

        self.new_inst(impl_inst)
    }
1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364

    fn build_destination(&mut self, fcb: &mut FuncCtxBuilder, id: MuID,
                         next_op_index: usize, inst_result_ids: &[MuID],
                         ) -> (Destination, Vec<P<TreeNode>>) {
        let dest_clause = self.b.bundle.dest_clauses.get(&id).unwrap();

        let target = dest_clause.dest;

        let mut next_my_index = next_op_index;
        let mut var_treenodes: Vec<P<TreeNode>> = Vec::new();

        let dest_args = dest_clause.vars.iter().map(|vid| {
            if let Some(ind) = inst_result_ids.iter().position(|rid| *rid == *vid) {
                DestArg::Freshbound(ind)
            } else {
                let treenode = self.get_treenode(fcb, *vid);
                let my_index = next_my_index;
                next_my_index += 1;
                var_treenodes.push(treenode);
                DestArg::Normal(my_index)
            }
        }).collect::<Vec<_>>();

        let impl_dest = Destination {
            target: target,
            args: dest_args,
        };

        (impl_dest, var_treenodes)
    }
1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382

    fn add_everything_to_vm(&mut self) {
        let vm = self.vm;

        trace!("Loading bundle to the VM...");

        vm.declare_many(
            &mut self.id_name_map,
            &mut self.built_types,
            &mut self.built_sigs,
            &mut self.built_constants,
            &mut self.built_globals,
            &mut self.built_funcs,
            &mut self.built_funcvers,
            );

        trace!("Bundle loaded to the VM!");
    }
1383
}