muirbuilder.rs 76.3 KB
Newer Older
1
use super::common::*;
2
use ast::op::*;
3
use ast::inst::*;
4
use utils::LinkedHashMap;
5
use utils::LinkedHashSet;
6
use std;
7

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

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

23
pub type IdBMap<T> = HashMap<MuID, Box<T>>;
24 25 26 27

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

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

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

58 59 60 61 62
    #[inline(always)]
    fn get_mvm_immutable<'a, 'b>(&'a self) -> &'b MuVM {
        unsafe { & *self.mvm }
    }

63
    #[inline(always)]
64
    fn get_vm<'a, 'b>(&'a mut self) -> &'b VM {
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
        &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();

qinsoon's avatar
qinsoon committed
103
        trace!("gen_sym({:?}) -> {}", name, my_id);
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121

        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) {
122
        self.bundle.types.insert(id, Box::new(NodeType::TypeFloat { id: id }));
123 124 125
    }

    pub fn new_type_double(&mut self, id: MuID) {
126
        self.bundle.types.insert(id, Box::new(NodeType::TypeDouble { id: id }));
127 128 129 130 131 132 133 134
    }

    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
135 136
        self.bundle.types.insert(id, Box::new(NodeType::TypeUFuncPtr{ id: id,
            sig: sig }));
137 138 139 140 141 142 143 144
    }

    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) {
145 146
        self.bundle.types.insert(id, Box::new(NodeType::TypeHybrid { id: id,
            fixedtys: fixedtys, varty: varty }));
147 148 149
    }

    pub fn new_type_array(&mut self, id: MuID, elemty: MuID, len: u64) {
150 151
        self.bundle.types.insert(id, Box::new(NodeType::TypeArray { id: id,
            elemty: elemty, len: len as usize }));
152 153 154
    }

    pub fn new_type_vector(&mut self, id: MuID, elemty: MuID, len: u64) {
155 156
        self.bundle.types.insert(id, Box::new(NodeType::TypeVector { id: id,
            elemty: elemty, len: len as usize }));
157 158 159
    }

    pub fn new_type_void(&mut self, id: MuID) {
160
        self.bundle.types.insert(id, Box::new(NodeType::TypeVoid { id: id }));
161 162 163
    }

    pub fn new_type_ref(&mut self, id: MuID, ty: MuID) {
164 165
        self.bundle.types.insert(id, Box::new(NodeType::TypeRef{ id: id,
            ty: ty }));
166 167 168
    }

    pub fn new_type_iref(&mut self, id: MuID, ty: MuID) {
169 170
        self.bundle.types.insert(id, Box::new(NodeType::TypeIRef{ id: id,
            ty: ty }));
171 172 173
    }

    pub fn new_type_weakref(&mut self, id: MuID, ty: MuID) {
174 175
        self.bundle.types.insert(id, Box::new(NodeType::TypeWeakRef{ id: id,
            ty: ty }));
176 177 178
    }

    pub fn new_type_funcref(&mut self, id: MuID, sig: MuID) {
179 180
        self.bundle.types.insert(id, Box::new(NodeType::TypeFuncRef{ id: id,
            sig: sig }));
181 182 183
    }

    pub fn new_type_tagref64(&mut self, id: MuID) {
184
        self.bundle.types.insert(id, Box::new(NodeType::TypeTagRef64 { id: id }));
185 186 187
    }

    pub fn new_type_threadref(&mut self, id: MuID) {
188
        self.bundle.types.insert(id, Box::new(NodeType::TypeThreadRef { id: id }));
189 190 191
    }

    pub fn new_type_stackref(&mut self, id: MuID) {
192
        self.bundle.types.insert(id, Box::new(NodeType::TypeStackRef { id: id }));
193 194 195
    }

    pub fn new_type_framecursorref(&mut self, id: MuID) {
196
        self.bundle.types.insert(id, Box::new(NodeType::TypeFrameCursorRef { id: id }));
197 198 199
    }

    pub fn new_type_irbuilderref(&mut self, id: MuID) {
200
        self.bundle.types.insert(id, Box::new(NodeType::TypeIRBuilderRef { id: id }));
201 202 203 204 205 206 207 208 209 210 211 212 213
    }

    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]) {
214 215
        self.bundle.consts.insert(id, Box::new(NodeConst::ConstIntEx {id: id,
            ty: ty, value: values.to_vec()}));
216 217 218
    }

    pub fn new_const_float(&mut self, id: MuID, ty: MuID, value: f32) {
219 220
        self.bundle.consts.insert(id, Box::new(NodeConst::ConstFloat { id: id,
            ty: ty, value: value }));
221 222 223
    }

    pub fn new_const_double(&mut self, id: MuID, ty: MuID, value: f64) {
224 225
        self.bundle.consts.insert(id, Box::new(NodeConst::ConstDouble { id: id,
            ty: ty, value: value }));
226 227 228
    }

    pub fn new_const_null(&mut self, id: MuID, ty: MuID) {
229 230
        self.bundle.consts.insert(id, Box::new(NodeConst::ConstNull { id: id,
            ty: ty }));
231 232 233
    }

    pub fn new_const_seq(&mut self, id: MuID, ty: MuID, elems: Vec<MuID>) {
234 235
        self.bundle.consts.insert(id, Box::new(NodeConst::ConstSeq { id: id,
            ty: ty, elems: elems }));
236 237 238
    }

    pub fn new_const_extern(&mut self, id: MuID, ty: MuID, symbol: String) {
239 240
        self.bundle.consts.insert(id, Box::new(NodeConst::ConstExtern { id: id,
            ty: ty, symbol: symbol }));
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263
    }

    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,
264 265
            nor_param_ids: nor_param_ids, nor_param_types: nor_param_types,
            exc_param_id: exc_param_id, insts: insts }));
266 267 268
    }

    pub fn new_dest_clause(&mut self, id: MuID, dest: MuID, vars: Vec<MuID>) {
269 270
        self.bundle.dest_clauses.insert(id, Box::new(NodeDestClause { id: id,
            dest: dest, vars: vars }));
271 272 273
    }

    pub fn new_exc_clause(&mut self, id: MuID, nor: MuID, exc: MuID) {
274 275
        self.bundle.exc_clauses.insert(id, Box::new(NodeExcClause { id: id,
            nor: nor, exc: exc }));
276 277 278
    }

    pub fn new_keepalive_clause(&mut self, id: MuID, vars: Vec<MuID>) {
279 280
        self.bundle.ka_clauses.insert(id, Box::new(NodeKeepaliveClause { id: id,
            vars: vars }));
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298
    }

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

299 300 301 302 303
    #[inline(always)]
    fn add_inst(&mut self, id: MuID, inst: NodeInst) {
        self.bundle.insts.insert(id, Box::new(inst));
    }

304
    pub fn new_binop(&mut self, id: MuID, result_id: MuID, optr: CMuBinOptr, ty: MuID, opnd1: MuID, opnd2: MuID, exc_clause: Option<MuID>) {
305 306
        self.add_inst(id, NodeInst::NodeBinOp {
            id: id, result_id: result_id, status_result_ids: vec![],
307
            optr: optr, flags: 0, ty: ty, opnd1: opnd1, opnd2: opnd2,
308 309
            exc_clause: exc_clause
        });
310 311 312
    }

    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>) {
qinsoon's avatar
qinsoon committed
313 314 315 316 317
        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,
            exc_clause: exc_clause
        })
318 319 320
    }

    pub fn new_cmp(&mut self, id: MuID, result_id: MuID, optr: CMuCmpOptr, ty: MuID, opnd1: MuID, opnd2: MuID) {
321 322 323 324
        self.add_inst(id, NodeInst::NodeCmp {
            id: id, result_id: result_id,
            optr: optr, ty: ty, opnd1: opnd1, opnd2: opnd2
        });
325 326 327
    }

    pub fn new_conv(&mut self, id: MuID, result_id: MuID, optr: CMuConvOptr, from_ty: MuID, to_ty: MuID, opnd: MuID) {
328 329 330 331
        self.add_inst(id, NodeInst::NodeConv {
            id: id, result_id: result_id,
            optr: optr, from_ty: from_ty, to_ty: to_ty, opnd: opnd
        });
332 333 334
    }

    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) {
335 336 337 338 339
        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
        });
340 341 342
    }

    pub fn new_branch(&mut self, id: MuID, dest: MuID) {
343 344 345
        self.add_inst(id, NodeInst::NodeBranch {
            id: id, dest: dest
        });
346 347 348
    }

    pub fn new_branch2(&mut self, id: MuID, cond: MuID, if_true: MuID, if_false: MuID) {
349 350 351
        self.add_inst(id, NodeInst::NodeBranch2 {
            id: id, cond: cond, if_true: if_true, if_false: if_false
        });
352 353 354
    }

    pub fn new_switch(&mut self, id: MuID, opnd_ty: MuID, opnd: MuID, default_dest: MuID, cases: Vec<MuID>, dests: Vec<MuID>) {
355 356 357 358
        self.add_inst(id, NodeInst::NodeSwitch {
            id: id, opnd_ty: opnd_ty, opnd: opnd, default_dest: default_dest,
            cases: cases, dests: dests
        });
359 360 361
    }

    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>) {
362 363 364 365 366
        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
        });
367 368 369
    }

    pub fn new_tailcall(&mut self, id: MuID, sig: MuID, callee: MuID, args: Vec<MuID>) {
370 371 372
        self.add_inst(id, NodeInst::NodeTailCall {
            id: id, sig: sig, callee: callee, args: args
        });
373 374 375
    }

    pub fn new_ret(&mut self, id: MuID, rvs: Vec<MuID>) {
376 377 378
        self.add_inst(id, NodeInst::NodeRet {
            id: id, rvs: rvs
        });
379 380 381
    }

    pub fn new_throw(&mut self, id: MuID, exc: MuID) {
382 383 384
        self.add_inst(id, NodeInst::NodeThrow {
            id: id, exc: exc
        });
385 386 387
    }

    pub fn new_extractvalue(&mut self, id: MuID, result_id: MuID, strty: MuID, index: c_int, opnd: MuID) {
388 389 390
        self.add_inst(id, NodeInst::NodeExtractValue {
            id: id, result_id: result_id, strty: strty, index: index, opnd: opnd
        });
391 392 393
    }

    pub fn new_insertvalue(&mut self, id: MuID, result_id: MuID, strty: MuID, index: c_int, opnd: MuID, newval: MuID) {
394 395 396
        self.add_inst(id, NodeInst::NodeInsertValue {
            id: id, result_id: result_id, strty: strty, index: index, opnd: opnd, newval: newval
        });
397 398 399
    }

    pub fn new_extractelement(&mut self, id: MuID, result_id: MuID, seqty: MuID, indty: MuID, opnd: MuID, index: MuID) {
400 401 402
        self.add_inst(id, NodeInst::NodeExtractElement {
            id: id, result_id: result_id, seqty: seqty, indty: indty, opnd: opnd, index: index
        });
403 404 405
    }

    pub fn new_insertelement(&mut self, id: MuID, result_id: MuID, seqty: MuID, indty: MuID, opnd: MuID, index: MuID, newval: MuID) {
406 407 408
        self.add_inst(id, NodeInst::NodeInsertElement {
            id: id, result_id: result_id, seqty: seqty, indty: indty, opnd: opnd, index: index, newval: newval
        });
409 410 411
    }

    pub fn new_shufflevector(&mut self, id: MuID, result_id: MuID, vecty: MuID, maskty: MuID, vec1: MuID, vec2: MuID, mask: MuID) {
412 413 414
        self.add_inst(id, NodeInst::NodeShuffleVector {
            id: id, result_id: result_id, vecty: vecty, maskty: maskty, vec1: vec1, vec2: vec2, mask: mask
        });
415 416 417
    }

    pub fn new_new(&mut self, id: MuID, result_id: MuID, allocty: MuID, exc_clause: Option<MuID>) {
418 419 420
        self.add_inst(id, NodeInst::NodeNew {
            id: id, result_id: result_id, allocty: allocty, exc_clause: exc_clause
        });
421 422 423
    }

    pub fn new_newhybrid(&mut self, id: MuID, result_id: MuID, allocty: MuID, lenty: MuID, length: MuID, exc_clause: Option<MuID>) {
424 425 426
        self.add_inst(id, NodeInst::NodeNewHybrid {
            id: id, result_id: result_id, allocty: allocty, lenty: lenty, length: length, exc_clause: exc_clause
        });
427 428 429
    }

    pub fn new_alloca(&mut self, id: MuID, result_id: MuID, allocty: MuID, exc_clause: Option<MuID>) {
430 431 432
        self.add_inst(id, NodeInst::NodeAlloca {
            id: id, result_id: result_id, allocty: allocty, exc_clause: exc_clause
        });
433 434 435
    }

    pub fn new_allocahybrid(&mut self, id: MuID, result_id: MuID, allocty: MuID, lenty: MuID, length: MuID, exc_clause: Option<MuID>) {
436 437 438
        self.add_inst(id, NodeInst::NodeAllocaHybrid {
            id: id, result_id: result_id, allocty: allocty, lenty: lenty, length: length, exc_clause: exc_clause
        });
439 440 441
    }

    pub fn new_getiref(&mut self, id: MuID, result_id: MuID, refty: MuID, opnd: MuID) {
442 443 444
        self.add_inst(id, NodeInst::NodeGetIRef {
            id: id, result_id: result_id, refty: refty, opnd: opnd
        });
445 446 447
    }

    pub fn new_getfieldiref(&mut self, id: MuID, result_id: MuID, is_ptr: bool, refty: MuID, index: c_int, opnd: MuID) {
448 449 450
        self.add_inst(id, NodeInst::NodeGetFieldIRef {
            id: id, result_id: result_id, is_ptr: is_ptr, refty: refty, index: index, opnd: opnd
        });
451 452 453
    }

    pub fn new_getelemiref(&mut self, id: MuID, result_id: MuID, is_ptr: bool, refty: MuID, indty: MuID, opnd: MuID, index: MuID) {
454 455 456
        self.add_inst(id, NodeInst::NodeGetElemIRef {
            id: id, result_id: result_id, is_ptr: is_ptr, refty: refty, indty: indty, opnd: opnd, index: index
        });
457 458 459
    }

    pub fn new_shiftiref(&mut self, id: MuID, result_id: MuID, is_ptr: bool, refty: MuID, offty: MuID, opnd: MuID, offset: MuID) {
460 461 462
        self.add_inst(id, NodeInst::NodeShiftIRef {
            id: id, result_id: result_id, is_ptr: is_ptr, refty: refty, offty: offty, opnd: opnd, offset: offset
        });
463 464 465
    }

    pub fn new_getvarpartiref(&mut self, id: MuID, result_id: MuID, is_ptr: bool, refty: MuID, opnd: MuID) {
466 467 468
        self.add_inst(id, NodeInst::NodeGetVarPartIRef {
            id: id, result_id: result_id, is_ptr: is_ptr, refty: refty, opnd: opnd
        });
469 470 471
    }

    pub fn new_load(&mut self, id: MuID, result_id: MuID, is_ptr: bool, ord: CMuMemOrd, refty: MuID, loc: MuID, exc_clause: Option<MuID>) {
472 473 474
        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
        });
475 476 477
    }

    pub fn new_store(&mut self, id: MuID, is_ptr: bool, ord: CMuMemOrd, refty: MuID, loc: MuID, newval: MuID, exc_clause: Option<MuID>) {
478 479 480
        self.add_inst(id, NodeInst::NodeStore {
            id: id, is_ptr: is_ptr, ord: ord, refty: refty, loc: loc, newval: newval, exc_clause: exc_clause
        });
481 482 483
    }

    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>) {
484 485 486
        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
        });
487 488 489
    }

    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>) {
490 491 492
        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
        });
493 494 495
    }

    pub fn new_fence(&mut self, id: MuID, ord: CMuMemOrd) {
496 497 498
        self.add_inst(id, NodeInst::NodeFence {
            id: id, ord: ord,
        });
499 500 501
    }

    pub fn new_trap(&mut self, id: MuID, result_ids: Vec<MuID>, rettys: Vec<MuID>, exc_clause: Option<MuID>, keepalive_clause: Option<MuID>) {
502 503 504
        self.add_inst(id, NodeInst::NodeTrap {
            id: id, result_ids: result_ids, rettys: rettys, exc_clause: exc_clause, keepalive_clause: keepalive_clause
        });
505 506
    }

507
    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>) {
508
        self.add_inst(id, NodeInst::NodeWatchPoint {
509
            id: id, wpid: wpid as MuID, result_ids: result_ids, rettys: rettys, dis: dis, ena: ena, exc: exc, keepalive_clause: keepalive_clause
510
        });
511 512
    }

513
    pub fn new_wpbranch(&mut self, id: MuID, wpid: CMuWPID, dis: MuID, ena: MuID) {
514
        self.add_inst(id, NodeInst::NodeWPBranch {
515
            id: id, wpid: wpid as MuID, dis: dis, ena: ena
516
        });
517 518 519
    }

    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>) {
520 521 522
        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
        });
523 524 525
    }

    pub fn new_newthread(&mut self, id: MuID, result_id: MuID, stack: MuID, threadlocal: Option<MuID>, new_stack_clause: MuID, exc_clause: Option<MuID>) {
526 527 528
        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
        });
529 530 531
    }

    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>) {
532 533 534
        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
        });
535 536 537
    }

    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>) {
538 539
        self.add_inst(id, NodeInst::NodeCommInst {
            id: id, result_ids: result_ids,
540
            opcode: opcode, flags: vec![], tys: tys, sigs: sigs, args: args,
541 542
            exc_clause: exc_clause, keepalive_clause: keepalive_clause
        });
543 544 545
    }
}

546
type IdPMap<T> = HashMap<MuID, P<T>>;
547

548 549 550
struct BundleLoader<'lb, 'lvm> {
    b: &'lb MuIRBuilder,
    vm: &'lvm VM,
551
    id_name_map: HashMap<MuID, MuName>,
552 553 554
    visited: HashSet<MuID>,
    built_types: IdPMap<MuType>,
    built_sigs: IdPMap<MuFuncSig>,
555 556 557 558
    built_constants: IdPMap<Value>,
    built_globals: IdPMap<Value>,
    built_funcs: IdBMap<MuFunction>,
    built_funcvers: IdBMap<MuFunctionVersion>,
559
    struct_hybrid_id_tags: Vec<(MuID, MuName)>,
qinsoon's avatar
qinsoon committed
560 561 562

    built_void: Option<P<MuType>>,
    built_refvoid: Option<P<MuType>>,
563
    built_refi64: Option<P<MuType>>,
564
    built_i1: Option<P<MuType>>,
565
    built_i64: Option<P<MuType>>,
qinsoon's avatar
qinsoon committed
566

567
    built_funcref_of: IdPMap<MuType>,
568
    built_ref_of: IdPMap<MuType>,
569
    built_iref_of: IdPMap<MuType>,
qinsoon's avatar
qinsoon committed
570 571
    built_uptr_of: IdPMap<MuType>,

572
    built_constint_of: HashMap<u64, P<Value>>,
573
}
574

575
fn load_bundle(b: &mut MuIRBuilder) {
576
    let vm = b.get_vm();
577

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

580 581 582
    let mut bl = BundleLoader {
        b: b,
        vm: vm,
583
        id_name_map: new_map,
584
        visited: Default::default(),
585
        built_types: Default::default(),
586
        built_sigs: Default::default(),
587 588
        built_constants: Default::default(),
        built_globals: Default::default(),
589
        built_funcs: Default::default(),
590
        built_funcvers: Default::default(),
591
        struct_hybrid_id_tags: Default::default(),
qinsoon's avatar
qinsoon committed
592 593
        built_void: Default::default(),
        built_refvoid: Default::default(),
594
        built_refi64: Default::default(),
595
        built_i1: Default::default(),
596
        built_i64: Default::default(),
597
        built_funcref_of: Default::default(),
598
        built_ref_of: Default::default(),
599
        built_iref_of: Default::default(),
qinsoon's avatar
qinsoon committed
600
        built_uptr_of: Default::default(),
601
        built_constint_of: Default::default(),
602 603 604
    };

    bl.load_bundle();
605 606
}

607 608 609 610
#[derive(Default)]
struct FuncCtxBuilder {
    ctx: FunctionContext,
    tree_nodes: IdPMap<TreeNode>,
611 612
}

613 614
const DEFAULT_TRUE_PROB: f32 = 0.6f32;

615 616
impl<'lb, 'lvm> BundleLoader<'lb, 'lvm> {
    fn load_bundle(&mut self) {
617 618
        self.ensure_names();
        self.build_toplevels();
619
        self.add_everything_to_vm();
620 621
    }

qinsoon's avatar
qinsoon committed
622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659
    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),
            v: MuType_::Void
        });

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

        trace!("Ensure refvoid is defined: {} {:?}", id_refvoid, impl_refvoid);

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

        impl_refvoid
    }

660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688
    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
    }

689
    fn ensure_i1(&mut self) -> P<MuType> {
690 691
        if let Some(ref impl_ty) = self.built_i1 {
            return impl_ty.clone();
692 693
        }

694
        let id = self.vm.next_id();
695

696 697
        let impl_ty = P(MuType {
            hdr: MuEntityHeader::unnamed(id),
698 699 700
            v: MuType_::Int(1),
        });

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

703 704
        self.built_types.insert(id, impl_ty.clone());
        self.built_i1 = Some(impl_ty.clone());
705

706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749
        impl_ty
    }

    fn ensure_i64(&mut self) -> P<MuType> {
        if let Some(ref impl_ty) = self.built_i64 {
            return impl_ty.clone();
        }

        let id = self.vm.next_id();

        let impl_ty = P(MuType {
            hdr: MuEntityHeader::unnamed(id),
            v: MuType_::Int(64),
        });

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

        self.built_types.insert(id, impl_ty.clone());
        self.built_i64 = Some(impl_ty.clone());

        impl_ty
    }

    fn ensure_constint_of(&mut self, value: u64) -> P<TreeNode> {
        if let Some(c) = self.built_constint_of.get(&value) {
            return self.new_global(c.clone());
        }

        let id = self.vm.next_id();

        let impl_ty = self.ensure_i64();

        let impl_val = P(Value {
            hdr: MuEntityHeader::unnamed(id),
            ty: impl_ty,
            v: Value_::Constant(Constant::Int(value)),
        });

        trace!("Ensure const int is defined: {} {:?}", value, impl_val);

        self.built_constants.insert(id, impl_val.clone());
        self.built_constint_of.insert(value, impl_val.clone());

        self.new_global(impl_val)
750
    }
751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772
    
    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
    }
773

774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806
    fn ensure_type_generic<F>(id: MuID, hint: &str,
                         vm: &VM, cache_map: &mut IdPMap<MuType>, storage_map: &mut IdPMap<MuType>,
                         factory: F) -> P<MuType> where F: Fn(P<MuType>) -> MuType_ {
        if let Some(obj) = cache_map.get(&id) {
            return obj.clone();
        }

        let new_id = vm.next_id();

        let old_obj = storage_map.get(&id).unwrap().clone();

        let impl_type_ = factory(old_obj);

        let new_obj = P(MuType {
            hdr: MuEntityHeader::unnamed(new_id),
            v: impl_type_,
        });

        storage_map.insert(new_id, new_obj.clone());

        trace!("Ensure {} of {} is defined: {:?}", hint, id, new_obj);

        cache_map.insert(new_id, new_obj.clone());

        new_obj
    }

    fn ensure_ref(&mut self, ty_id: MuID) -> P<MuType> {
        BundleLoader::ensure_type_generic(ty_id, "ref", &self.vm, &mut self.built_ref_of, &mut self.built_types, |impl_ty| {
            MuType_::Ref(impl_ty)
        })
    }

807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826
    fn ensure_iref(&mut self, ty_id: MuID) -> P<MuType> {
        BundleLoader::ensure_type_generic(ty_id, "iref", &self.vm, &mut self.built_iref_of, &mut self.built_types, |impl_ty| {
            MuType_::IRef(impl_ty)
        })
    }

    fn ensure_uptr(&mut self, ty_id: MuID) -> P<MuType> {
        BundleLoader::ensure_type_generic(ty_id, "uptr", &self.vm, &mut self.built_iref_of, &mut self.built_types, |impl_ty| {
            MuType_::UPtr(impl_ty)
        })
    }

    fn ensure_iref_or_uptr(&mut self, ty_id: MuID, is_ptr: bool) -> P<MuType> {
        if is_ptr {
            self.ensure_uptr(ty_id)
        } else {
            self.ensure_iref(ty_id)
        }
    }

827
    fn name_from_id(id: MuID, hint: &str) -> String {
828
        format!("@uvm.unnamed.{}{}", hint, id)
829 830 831 832 833 834 835 836 837 838 839
    }

    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) {
840
        // Make sure structs and hybrids have names because names are used to resolve cyclic
841 842 843 844 845 846
        // dependencies.
        for (id, ty) in &self.b.bundle.types {
            match **ty {
                NodeType::TypeStruct { id: _, fieldtys: _ } => { 
                    self.ensure_name(*id, "struct");
                },
847 848 849
                NodeType::TypeHybrid { id: _, fixedtys: _, varty: _ } => { 
                    self.ensure_name(*id, "struct");
                },
850 851 852
                _ => {}
            }
        }
853 854 855 856 857 858 859 860

        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");
        }
861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878
    }

    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) {
879
        for id in self.b.bundle.types.keys() {
880 881 882 883 884
            if !self.visited.contains(id) {
                self.build_type(*id)
            }
        }

885 886 887
        let struct_hybrid_id_tags = self.struct_hybrid_id_tags.drain(..).collect::<Vec<_>>();
        for (id, ref tag) in struct_hybrid_id_tags {
            self.fill_struct_hybrid(id, tag)
888
        }
Kunshan Wang's avatar
Kunshan Wang committed
889 890 891 892 893 894

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

896 897 898 899
        for id in self.b.bundle.consts.keys() {
            if !self.visited.contains(id) {
                self.build_const(*id)
            }
900
        }
901

902 903 904 905 906 907
        for id in self.b.bundle.globals.keys() {
            if !self.visited.contains(id) {
                self.build_global(*id)
            }
        }

908 909 910 911 912
        for id in self.b.bundle.funcs.keys() {
            if !self.visited.contains(id) {
                self.build_func(*id)
            }
        }
913 914 915 916

        for id in self.b.bundle.funcvers.keys() {
            self.build_funcver(*id)
        }
917
    }
918

919 920 921 922
    fn build_type(&mut self, id: MuID) {
        self.visited.insert(id);

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

924 925
        trace!("Building type {} {:?}", id, ty);

926 927 928
        let hdr = self.make_mu_entity_header(id);

        let impl_ty_ = match **ty {
929
            NodeType::TypeInt { id: _, len } => {
930
                MuType_::Int(len as usize)
931
            },
932 933 934 935 936 937
            NodeType::TypeFloat { id: _ } => {
                MuType_::Float
            },
            NodeType::TypeDouble { id: _ } => {
                MuType_::Double
            },
938
            NodeType::TypeUPtr { id: _, ty: toty } => {
939 940
                let impl_toty = self.ensure_type_rec(toty);
                MuType_::UPtr(impl_toty)
941
            },
942 943 944
            NodeType::TypeUFuncPtr { id: _, sig } => {
                let impl_sig = self.ensure_sig_rec(sig);
                MuType_::UFuncPtr(impl_sig)
Kunshan Wang's avatar
Kunshan Wang committed
945
            },
946
            NodeType::TypeStruct { id: _, fieldtys: _ } => { 
947
                let tag = self.get_name(id);
948 949 950
                self.struct_hybrid_id_tags.push((id, tag.clone()));
                MuType_::mustruct_empty(tag)
                // MuType_::Struct(tag)
951
            },
952 953 954 955
            NodeType::TypeHybrid { id: _, fixedtys: _, varty: _ } => {
                let tag = self.get_name(id);
                self.struct_hybrid_id_tags.push((id, tag.clone()));
                MuType_::hybrid_empty(tag)
956 957 958
//                let impl_fixedtys = fixedtys.iter().map(|t| self.ensure_type_rec(*t)).collect::<Vec<_>>();
//                let impl_varty = self.ensure_type_rec(varty);
//                MuType_::Hybrid(impl_fixedtys, impl_varty)
959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995
            },
            NodeType::TypeArray { id: _, elemty, len } => { 
                let impl_elemty = self.ensure_type_rec(elemty);
                MuType_::Array(impl_elemty, len)
            },
            NodeType::TypeVector { id: _, elemty, len } => { 
                let impl_elemty = self.ensure_type_rec(elemty);
                MuType_::Vector(impl_elemty, len)
            },
            NodeType::TypeVoid { id: _ } => {
                MuType_::Void
            },
            NodeType::TypeTagRef64 { id: _ } => {
                MuType_::Tagref64
            },
            NodeType::TypeRef { id: _, ty: toty } => {
                let impl_toty = self.ensure_type_rec(toty);
                MuType_::Ref(impl_toty)
            },
            NodeType::TypeIRef { id: _, ty: toty } => {
                let impl_toty = self.ensure_type_rec(toty);
                MuType_::IRef(impl_toty)
            },
            NodeType::TypeWeakRef { id: _, ty: toty } => {
                let impl_toty = self.ensure_type_rec(toty);
                MuType_::WeakRef(impl_toty)
            },
            NodeType::TypeFuncRef { id: _, sig } => {
                let impl_sig = self.ensure_sig_rec(sig);
                MuType_::FuncRef(impl_sig)
            },
            NodeType::TypeThreadRef { id: _ } => {
                MuType_::ThreadRef
            },
            NodeType::TypeStackRef { id: _ } => {
                MuType_::StackRef
            },
996
            ref t => panic!("{:?} not implemented", t),
997 998 999
        };

        let impl_ty = MuType { hdr: hdr, v: impl_ty_ };
1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015

        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()
1016 1017
            }
        } else {
1018
            self.vm.get_type(id)
1019
        }
1020
    }
1021

1022 1023 1024 1025 1026 1027 1028
    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)
        }
    }

1029
    fn fill_struct_hybrid(&mut self, id: MuID, tag: &MuName) {
1030
        let ty = self.b.bundle.types.get(&id).unwrap();
1031

1032
        trace!("Filling struct or hybrid {} {:?}", id, ty);
1033 1034

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

1040
                MuType_::mustruct_put(tag, fieldtys_impl);
1041

1042
                trace!("Struct {} filled: {:?}", id,
1043
                       STRUCT_TAG_MAP.read().unwrap().get(tag));
1044
            },
1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057
            NodeType::TypeHybrid { id: _, ref fixedtys, varty } => { 
                let fixedtys_impl = fixedtys.iter().map(|fid| {
                    self.ensure_type_rec(*fid)
                }).collect::<Vec<_>>();

                let varty_impl = self.ensure_type_rec(varty);

                MuType_::hybrid_put(tag, fixedtys_impl, varty_impl);

                trace!("Hybrid {} filled: {:?}", id,
                       HYBRID_TAG_MAP.read().unwrap().get(tag));
            },
            ref t => panic!("{} {:?} should be a Struct or Hybrid type", id, ty),
1058 1059
        }
    }
Kunshan Wang's avatar
Kunshan Wang committed
1060 1061 1062 1063 1064

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

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

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

1068 1069
        let hdr = self.make_mu_entity_header(id);

Kunshan Wang's avatar
Kunshan Wang committed
1070
        let impl_sig = MuFuncSig{
1071
            hdr: hdr,
Kunshan Wang's avatar
Kunshan Wang committed
1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095
            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)
        }
    }
1096 1097 1098 1099 1100

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

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

1102 1103 1104 1105 1106
        trace!("Building constant {} {:?}", id, con);

        let hdr = self.make_mu_entity_header(id);

        let (impl_con, impl_ty) = match **con {
1107
            NodeConst::ConstInt { id: _, ty, value } => {
1108 1109 1110 1111
                let t = self.ensure_type_rec(ty);
                let c = Constant::Int(value);
                (c, t)
            },
1112 1113 1114 1115 1116
            NodeConst::ConstIntEx { id: _, ty, ref value } => {
                let t = self.ensure_type_rec(ty);
                let c = Constant::IntEx(value.clone());
                (c, t)
            },
1117
            NodeConst::ConstFloat { id: _, ty, value } => {
1118 1119 1120 1121
                let t = self.ensure_type_rec(ty);
                let c = Constant::Float(value);
                (c, t)
            },
1122
            NodeConst::ConstDouble { id: _, ty, value } => {
1123 1124 1125 1126
                let t = self.ensure_type_rec(ty);
                let c = Constant::Double(value);
                (c, t)
            },
1127
            NodeConst::ConstNull { id: _, ty } => {
1128 1129 1130 1131
                let t = self.ensure_type_rec(ty);
                let c = Constant::NullRef;
                (c, t)
            },
1132 1133 1134 1135 1136
            NodeConst::ConstExtern { id: _, ty, ref symbol } => {
                let t = self.ensure_type_rec(ty);
                let c = Constant::ExternSym(symbol.clone());
                (c, t)
            },
1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147
            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);

1148
        self.built_constants.insert(id, P(impl_val));
1149
    }
1150

1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171
    fn build_global(&mut self, id: MuID) {
        self.visited.insert(id);

        let global = self.b.bundle.globals.get(&id).unwrap();

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

        let hdr = self.make_mu_entity_header(id);
        let impl_ty = self.ensure_type_rec(global.ty); // global type

        let impl_val = Value {
            hdr: hdr,
            ty: self.ensure_iref(impl_ty.id()), // iref to global
            v: Value_::Global(impl_ty)
        };

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

        self.built_globals.insert(id, P(impl_val));
    }

1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182
    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 {
1183
            hdr: hdr.clone(),
1184 1185 1186 1187 1188 1189 1190
            sig: impl_sig,
            cur_ver: None,
            all_vers: Default::default(),
        };

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

1191
        self.built_funcs.insert(id, Box::new(impl_fun));
1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202

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

1203
        self.built_constants.insert(id, P(impl_val));
1204
    }
1205

1206 1207 1208 1209 1210 1211 1212 1213 1214
    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)
        }
    }


1215 1216
    fn build_funcver(&mut self, id: MuID) {
        let fv = self.b.bundle.funcvers.get(&id).unwrap();
1217

1218 1219 1220
        trace!("Building function version {} {:?}", id, fv);

        let hdr = self.make_mu_entity_header(id);
1221 1222
        let func_id = fv.func;
        let impl_sig = self.get_sig_for_func(func_id);
1223

1224
        let mut fcb: FuncCtxBuilder = Default::default();
1225 1226

        let blocks = fv.bbs.iter().map(|bbid| {
1227
            let block = self.build_block(&mut fcb, *bbid);
1228
            (*bbid, block)
1229
        }).collect::<LinkedHashMap<MuID, Block>>();
1230 1231 1232 1233 1234

        let entry_id = *fv.bbs.first().unwrap();
        let ctn = FunctionContent {
            entry: entry_id,
            blocks: blocks,
1235
            exception_blocks: LinkedHashSet::new()
1236 1237
        };

qinsoon's avatar
[wip]  
qinsoon committed
1238
        let impl_fv = MuFunctionVersion::new_(hdr, func_id, impl_sig, ctn, fcb.ctx);
1239 1240 1241

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

1242
        self.built_funcvers.insert(id, Box::new(impl_fv));
1243 1244 1245 1246 1247
    }

    /// 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.
1248
    fn new_ssa(&self, fcb: &mut FuncCtxBuilder, id: MuID, ty: P<MuType>) -> P<TreeNode> {
1249 1250 1251 1252 1253 1254 1255
        let hdr = self.make_mu_entity_header(id);
        let val = P(Value{
            hdr: hdr,
            ty: ty,
            v: Value_::SSAVar(id)
        });

1256
        fcb.ctx.values.insert(id, SSAVarEntry::new(val.clone()));
1257

1258
        let tn = P(TreeNode {
1259 1260
            op: pick_op_code_for_ssa(&val.ty),
            v: TreeNode_::Value(val)
1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273
        });

        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),
        })
    }
1274

1275 1276 1277 1278
    pub fn new_global(&self, v: P<Value>) -> P<TreeNode> {
        P(TreeNode{
            op: pick_op_code_for_value(&v.ty),
            v: TreeNode_::Value(v)