WARNING! Access to this system is limited to authorised users only.
Unauthorised users may be subject to prosecution.
Unauthorised access to this system is a criminal offence under Australian law (Federal Crimes Act 1914 Part VIA)
It is a criminal offence to:
(1) Obtain access to data without authority. -Penalty 2 years imprisonment.
(2) Damage, delete, alter or insert data without authority. -Penalty 10 years imprisonment.
User activity is monitored and recorded. Anyone using this system expressly consents to such monitoring and recording.

To protect your data, the CISO officer has suggested users to enable 2FA as soon as possible.
Currently 2.7% of users enabled 2FA.

ir.rs 17.9 KB
Newer Older
1
use ast::ptr::P;
qinsoon's avatar
qinsoon committed
2
use ast::op::*;
3
4
use ast::types::*;

5
use std::collections::HashMap;
qinsoon's avatar
qinsoon committed
6
use std::fmt;
qinsoon's avatar
qinsoon committed
7
use std::cell::Cell;
8
use std::cell::RefCell;
qinsoon's avatar
qinsoon committed
9

qinsoon's avatar
qinsoon committed
10
11
12
13
14
pub type WPID  = usize;
pub type MuID  = usize;
pub type MuTag = &'static str;
pub type Address = usize; // TODO: replace this with Address(usize)

15
16
pub type OpIndex = usize;

17
#[derive(Debug)]
qinsoon's avatar
qinsoon committed
18
19
20
pub struct MuFunction {
    pub fn_name: MuTag,
    pub sig: P<MuFuncSig>,
21
    pub content: Option<FunctionContent>,
qinsoon's avatar
qinsoon committed
22
    pub context: FunctionContext
23
24
25
26
}

#[derive(Debug)]
pub struct FunctionContent {
qinsoon's avatar
qinsoon committed
27
28
    pub entry: MuTag,
    pub blocks: Vec<(MuTag, Block)>
qinsoon's avatar
qinsoon committed
29
30
}

qinsoon's avatar
qinsoon committed
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#[derive(Debug)]
pub struct FunctionContext {
    pub values: HashMap<MuID, ValueEntry>
}

impl FunctionContext {
    fn new() -> FunctionContext {
        FunctionContext {
            values: HashMap::new()
        }
    }
    
    pub fn get_value(&self, id: MuID) -> Option<&ValueEntry> {
        self.values.get(&id)
    }
46
47
48
49
    
    pub fn get_value_mut(&mut self, id: MuID) -> Option<&mut ValueEntry> {
        self.values.get_mut(&id)
    }
qinsoon's avatar
qinsoon committed
50
51
}

52
53
impl MuFunction {
    pub fn new(fn_name: MuTag, sig: P<MuFuncSig>) -> MuFunction {
qinsoon's avatar
qinsoon committed
54
        MuFunction{fn_name: fn_name, sig: sig, content: None, context: FunctionContext::new()}
55
56
57
58
59
60
61
    }
    
    pub fn define(&mut self, content: FunctionContent) {
        self.content = Some(content)
    }
    
    pub fn new_ssa(&mut self, id: MuID, tag: MuTag, ty: P<MuType>) -> P<TreeNode> {
62
        self.context.values.insert(id, ValueEntry{id: id, tag: tag, ty: ty.clone(), use_count: Cell::new(0), expr: None});
63
64
        
        P(TreeNode {
qinsoon's avatar
qinsoon committed
65
66
67
68
69
            v: TreeNode_::Value(P(Value{
                tag: tag,
                ty: ty,
                v: Value_::SSAVar(id)
            }))
70
71
72
        })
    }
    
qinsoon's avatar
qinsoon committed
73
    pub fn new_constant(&mut self, tag: MuTag, ty: P<MuType>, v: Constant) -> P<TreeNode> {
74
        P(TreeNode{
qinsoon's avatar
qinsoon committed
75
76
77
78
79
80
            v: TreeNode_::Value(P(Value{
                tag: tag,
                ty: ty, 
                v: Value_::Constant(v)
            }))
        })
81
82
83
84
    }
    
    pub fn new_value(&mut self, v: P<Value>) -> P<TreeNode> {
        P(TreeNode{
qinsoon's avatar
qinsoon committed
85
86
            v: TreeNode_::Value(v)
        })
87
88
89
    }    
}

90
#[derive(Debug)]
91
pub struct Block {
92
93
    pub label: MuTag,
    pub content: Option<BlockContent>
qinsoon's avatar
qinsoon committed
94
95
}

96
97
98
99
100
101
impl Block {
    pub fn new(label: MuTag) -> Block {
        Block{label: label, content: None}
    }
}

102
#[derive(Debug)]
103
pub struct BlockContent {
qinsoon's avatar
qinsoon committed
104
105
106
    pub args: Vec<P<TreeNode>>,
    pub body: Vec<P<TreeNode>>,
    pub keepalives: Option<Vec<P<TreeNode>>>    
107
108
}

109
#[derive(Debug, Clone)]
qinsoon's avatar
qinsoon committed
110
111
/// always use with P<TreeNode>
pub struct TreeNode {
qinsoon's avatar
qinsoon committed
112
//    pub op: OpCode,
113
    pub v: TreeNode_
qinsoon's avatar
qinsoon committed
114
115
}

116
117
118
impl TreeNode {   
    pub fn new_inst(v: Instruction) -> P<TreeNode> {
        P(TreeNode{v: TreeNode_::Instruction(v)})
qinsoon's avatar
qinsoon committed
119
    }
120
121
122
123
124
125
126
127
128
129
130
131
    
    pub fn extract_ssa_id(&self) -> Option<MuID> {
        match self.v {
            TreeNode_::Value(ref pv) => {
                match pv.v {
                    Value_::SSAVar(id) => Some(id),
                    _ => None
                }
            },
            _ => None
        }
    }
qinsoon's avatar
qinsoon committed
132
133
}

134
135
/// use +() to display a node
impl fmt::Display for TreeNode {
qinsoon's avatar
qinsoon committed
136
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
137
138
139
        match self.v {
            TreeNode_::Value(ref pv) => {
                match pv.v {
140
                    Value_::SSAVar(id) => {
141
                        write!(f, "+({} %{}#{})", pv.ty, pv.tag, id)
142
143
                    },
                    Value_::Constant(ref c) => {
144
                        write!(f, "+({} {})", pv.ty, c) 
145
146
147
148
                    }
                }
            },
            TreeNode_::Instruction(ref inst) => {
149
                write!(f, "+({})", inst)
150
            }
qinsoon's avatar
qinsoon committed
151
        }
qinsoon's avatar
qinsoon committed
152
    }
qinsoon's avatar
qinsoon committed
153
154
}

155
#[derive(Debug, Clone)]
qinsoon's avatar
qinsoon committed
156
pub enum TreeNode_ {
qinsoon's avatar
qinsoon committed
157
    Value(P<Value>),
158
    Instruction(Instruction)
qinsoon's avatar
qinsoon committed
159
160
161
}

/// always use with P<Value>
162
#[derive(Debug, Clone)]
qinsoon's avatar
qinsoon committed
163
pub struct Value {
164
    pub tag: MuTag,
qinsoon's avatar
qinsoon committed
165
166
    pub ty: P<MuType>,
    pub v: Value_
qinsoon's avatar
qinsoon committed
167
168
}

169
#[derive(Debug, Clone)]
qinsoon's avatar
qinsoon committed
170
pub enum Value_ {
171
    SSAVar(MuID),
qinsoon's avatar
qinsoon committed
172
    Constant(Constant)
qinsoon's avatar
qinsoon committed
173
174
}

175
#[derive(Debug, Clone)]
176
177
178
179
pub struct ValueEntry {
    pub id: MuID,
    pub tag: MuTag,
    pub ty: P<MuType>,
180
181
182
183
184
185
186
187
    pub use_count: Cell<usize>,  // how many times this entry is used
    pub expr: Option<Instruction>
}

impl ValueEntry {
    pub fn assign_expr(&mut self, expr: Instruction) {
        self.expr = Some(expr)
    }
188
189
}

190
impl fmt::Display for ValueEntry {
191
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
192
        write!(f, "{} {}#{}", self.ty, self.tag, self.id)
193
194
195
    }
}

196
#[derive(Debug, Clone)]
197
pub enum Constant {
198
199
200
201
202
203
204
205
206
    Int(usize),
    Float(f32),
    Double(f64),
    IRef(Address),
    FuncRef(Address),
    UFuncRef(Address),
    Vector(Vec<Constant>),    
}

207
impl fmt::Display for Constant {
208
209
210
211
212
213
214
215
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &Constant::Int(v) => write!(f, "{}", v),
            &Constant::Float(v) => write!(f, "{}", v),
            &Constant::Double(v) => write!(f, "{}", v),
            &Constant::IRef(v) => write!(f, "{}", v),
            &Constant::FuncRef(v) => write!(f, "{}", v),
            &Constant::UFuncRef(v) => write!(f, "{}", v),
216
217
218
219
220
221
222
223
224
225
            &Constant::Vector(ref v) => {
                write!(f, "[").unwrap();
                for i in 0..v.len() {
                    write!(f, "{}", v[i]).unwrap();
                    if i != v.len() - 1 {
                        write!(f, ", ").unwrap();
                    }
                }
                write!(f, "]")
            }
226
227
        }
    }
qinsoon's avatar
qinsoon committed
228
229
}

230
#[derive(Debug, Clone)]
231
232
233
234
pub struct Instruction {
    pub value : Option<Vec<P<TreeNode>>>,
    pub ops : RefCell<Vec<P<TreeNode>>>,
    pub v: Instruction_
qinsoon's avatar
qinsoon committed
235
236
}

qinsoon's avatar
qinsoon committed
237
238
239
240
241
242
impl Instruction {
    fn debug_str(&self, ops: &Vec<P<TreeNode>>) -> String {
        self.v.debug_str(ops)
    }
}

243
impl fmt::Display for Instruction {
qinsoon's avatar
qinsoon committed
244
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
qinsoon's avatar
qinsoon committed
245
246
        let ops = &self.ops.borrow();
        if self.value.is_some() {
247
            write!(f, "{} = {}", node_vector_str(self.value.as_ref().unwrap()), self.v.debug_str(ops))
qinsoon's avatar
qinsoon committed
248
249
250
        } else {
            write!(f, "{}", self.v.debug_str(ops))
        }
251
252
253
    }
}

254
#[derive(Debug, Clone)]
255
256
257
258
259
260
261
pub enum Instruction_ {
    // non-terminal instruction
    
    // expressions
    
    BinOp(BinOp, OpIndex, OpIndex), 
    CmpOp(CmpOp, OpIndex, OpIndex),
qinsoon's avatar
qinsoon committed
262
263
264
265
266
267
268
269
270
    
    // yields a tuple of results from the call
    ExprCall{
        data: CallData,
        is_abort: bool, // T to abort, F to rethrow
    },
    
    // yields the memory value
    Load{
271
272
        is_ptr: bool,
        order: MemoryOrder,
273
        mem_loc: OpIndex
qinsoon's avatar
qinsoon committed
274
    },
qinsoon's avatar
qinsoon committed
275
    
qinsoon's avatar
qinsoon committed
276
277
    // yields nothing
    Store{
278
279
        is_ptr: bool,
        order: MemoryOrder,        
280
281
        mem_loc: OpIndex,
        value: OpIndex
qinsoon's avatar
qinsoon committed
282
283
284
    },
    
    // yields pair (oldvalue, boolean (T = success, F = failure))
qinsoon's avatar
qinsoon committed
285
    CmpXchg{
286
287
        is_ptr: bool,
        is_weak: bool,
qinsoon's avatar
qinsoon committed
288
289
        success_order: MemoryOrder,
        fail_order: MemoryOrder,
290
291
292
        mem_loc: OpIndex,
        expected_value: OpIndex,
        desired_value: OpIndex
qinsoon's avatar
qinsoon committed
293
294
    },
    
qinsoon's avatar
qinsoon committed
295
    // yields old memory value
qinsoon's avatar
qinsoon committed
296
    AtomicRMW{
297
        is_ptr: bool, // T for iref, F for ptr
qinsoon's avatar
qinsoon committed
298
299
        order: MemoryOrder,
        op: AtomicRMWOp,
300
301
        mem_loc: OpIndex,
        value: OpIndex // operand for op
qinsoon's avatar
qinsoon committed
302
303
    },
    
qinsoon's avatar
qinsoon committed
304
    // yields a reference of the type
qinsoon's avatar
qinsoon committed
305
    New(P<MuType>),
qinsoon's avatar
qinsoon committed
306
307
    
    // yields an iref of the type
qinsoon's avatar
qinsoon committed
308
    AllocA(P<MuType>),
qinsoon's avatar
qinsoon committed
309
310
    
    // yields ref
311
    NewHybrid(P<MuType>, OpIndex),
qinsoon's avatar
qinsoon committed
312
313
    
    // yields iref
314
    AllocAHybrid(P<MuType>, OpIndex),
qinsoon's avatar
qinsoon committed
315
316
    
    // yields stack ref
317
    NewStack(OpIndex), // func
318
                           // TODO: common inst
qinsoon's avatar
qinsoon committed
319
320
    
    // yields thread reference
321
    NewThread(OpIndex, Vec<OpIndex>), // stack, args
qinsoon's avatar
qinsoon committed
322
323
    
    // yields thread reference (thread resumes with exceptional value)
324
    NewThreadExn(OpIndex, OpIndex), // stack, exception
qinsoon's avatar
qinsoon committed
325
    
qinsoon's avatar
qinsoon committed
326
    // yields frame cursor
327
    NewFrameCursor(OpIndex), // stack
qinsoon's avatar
qinsoon committed
328
    
329
    // ref<T> -> iref<T>
330
    GetIRef(OpIndex),
qinsoon's avatar
qinsoon committed
331
    
332
    // iref|uptr<struct|hybrid<T>> int<M> -> iref|uptr<U>
qinsoon's avatar
qinsoon committed
333
    GetFieldIRef{
334
        is_ptr: bool,
335
336
        base: OpIndex, // iref or uptr
        index: OpIndex // constant
qinsoon's avatar
qinsoon committed
337
    },
qinsoon's avatar
qinsoon committed
338
    
339
    // iref|uptr<array<T N>> int<M> -> iref|uptr<T>
qinsoon's avatar
qinsoon committed
340
    GetElementIRef{
341
        is_ptr: bool,
342
343
        base: OpIndex,
        index: OpIndex // can be constant or ssa var
qinsoon's avatar
qinsoon committed
344
345
    },
    
346
    // iref|uptr<T> int<M> -> iref|uptr<T>
qinsoon's avatar
qinsoon committed
347
    ShiftIRef{
348
        is_ptr: bool,
349
350
        base: OpIndex,
        offset: OpIndex
qinsoon's avatar
qinsoon committed
351
352
    },
    
353
354
355
    // iref|uptr<hybrid<T U>> -> iref|uptr<U>
    GetVarPartIRef{
        is_ptr: bool,
356
        base: OpIndex
357
    },
qinsoon's avatar
qinsoon committed
358
359
360
361
362
363
364
365
    
//    PushFrame{
//        stack: P<Value>,
//        func: P<Value>
//    },
//    PopFrame{
//        stack: P<Value>
//    }
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412

    Fence(MemoryOrder),
    
    // terminal instruction
    Return(Vec<OpIndex>),
    ThreadExit, // TODO:  common inst
    Throw(Vec<OpIndex>),
    TailCall(CallData),
    Branch1(Destination),
    Branch2{
        cond: OpIndex,
        true_dest: Destination,
        false_dest: Destination
    },
    Watchpoint{ // Watchpoint NONE ResumptionData
                //   serves as an unconditional trap. Trap to client, and resume with ResumptionData
                // Watchpoint (WPID dest) ResumptionData
                //   when disabled, jump to dest
                //   when enabled, trap to client and resume
        id: Option<WPID>,
        disable_dest: Option<Destination>,
        resume: ResumptionData
    }, 
    WPBranch{
        wp: WPID, 
        disable_dest: Destination,
        enable_dest: Destination
    },
    Call{
        data: CallData,
        resume: ResumptionData
    },
    SwapStack{
        stack: OpIndex,
        is_exception: bool,
        args: Vec<OpIndex>,
        resume: ResumptionData
    },
    Switch{
        cond: OpIndex,
        default: Destination,
        branches: Vec<(OpIndex, Destination)>
    },
    ExnInstruction{
        inner: P<Instruction>,
        resume: ResumptionData
    }
qinsoon's avatar
qinsoon committed
413
414
}

415
416
417
418
419
420
421
422
423
424
macro_rules! select {
    ($cond: expr, $res1 : expr, $res2 : expr) => {
        if $cond {
            $res1
        } else {
            $res2
        }
    }
}

qinsoon's avatar
qinsoon committed
425
426
427
impl Instruction_ {
    fn debug_str(&self, ops: &Vec<P<TreeNode>>) -> String {
        match self {
428
429
            &Instruction_::BinOp(op, op1, op2) => format!("{:?} {} {}", op, ops[op1], ops[op2]),
            &Instruction_::CmpOp(op, op1, op2) => format!("{:?} {} {}", op, ops[op1], ops[op2]),
qinsoon's avatar
qinsoon committed
430
431
            &Instruction_::ExprCall{ref data, is_abort} => {
                let abort = select!(is_abort, "ABORT_ON_EXN", "RETHROW");
432
                format!("CALL {} {}", data.debug_str(ops), abort)
qinsoon's avatar
qinsoon committed
433
434
435
            },
            &Instruction_::Load{is_ptr, mem_loc, order} => {
                let ptr = select!(is_ptr, "PTR", "");
436
                format!("LOAD {} {:?} {}", ptr, order, ops[mem_loc]) 
qinsoon's avatar
qinsoon committed
437
438
439
            },
            &Instruction_::Store{value, is_ptr, mem_loc, order} => {
                let ptr = select!(is_ptr, "PTR", "");
440
                format!("STORE {} {:?} {} {}", ptr, order, ops[mem_loc], ops[value])
qinsoon's avatar
qinsoon committed
441
442
443
444
445
            },
            &Instruction_::CmpXchg{is_ptr, is_weak, success_order, fail_order, 
                mem_loc, expected_value, desired_value} => {
                let ptr = select!(is_ptr, "PTR", "");
                let weak = select!(is_weak, "WEAK", "");
446
447
                format!("CMPXCHG {} {} {:?} {:?} {} {} {}", 
                    ptr, weak, success_order, fail_order, ops[mem_loc], ops[expected_value], ops[desired_value])  
qinsoon's avatar
qinsoon committed
448
449
450
            },
            &Instruction_::AtomicRMW{is_ptr, order, op, mem_loc, value} => {
                let ptr = select!(is_ptr, "PTR", "");
451
                format!("ATOMICRMW {} {:?} {:?} {} {}", ptr, order, op, ops[mem_loc], ops[value])
qinsoon's avatar
qinsoon committed
452
            },
453
454
455
456
457
458
459
460
461
            &Instruction_::New(ref ty) => format!("NEW {}", ty),
            &Instruction_::AllocA(ref ty) => format!("ALLOCA {}", ty),
            &Instruction_::NewHybrid(ref ty, len) => format!("NEWHYBRID {} {}", ty, ops[len]),
            &Instruction_::AllocAHybrid(ref ty, len) => format!("ALLOCAHYBRID {} {}", ty, ops[len]),
            &Instruction_::NewStack(func) => format!("NEWSTACK {}", ops[func]),
            &Instruction_::NewThread(stack, ref args) => format!("NEWTHREAD {} PASS_VALUES {}", ops[stack], op_vector_str(args, ops)),
            &Instruction_::NewThreadExn(stack, exn) => format!("NEWTHREAD {} THROW_EXC {}", ops[stack], ops[exn]),
            &Instruction_::NewFrameCursor(stack) => format!("NEWFRAMECURSOR {}", ops[stack]),
            &Instruction_::GetIRef(reference) => format!("GETIREF {}", ops[reference]),
qinsoon's avatar
qinsoon committed
462
463
            &Instruction_::GetFieldIRef{is_ptr, base, index} => {
                let ptr = select!(is_ptr, "PTR", "");
464
                format!("GETFIELDIREF {} {} {}", ptr, ops[base], ops[index])
qinsoon's avatar
qinsoon committed
465
466
467
            },
            &Instruction_::GetElementIRef{is_ptr, base, index} => {
                let ptr = select!(is_ptr, "PTR", "");
468
                format!("GETELEMENTIREF {} {} {}", ptr, ops[base], ops[index])
qinsoon's avatar
qinsoon committed
469
470
471
            },
            &Instruction_::ShiftIRef{is_ptr, base, offset} => {
                let ptr = select!(is_ptr, "PTR", "");
472
                format!("SHIFTIREF {} {} {}", ptr, ops[base], ops[offset])
qinsoon's avatar
qinsoon committed
473
474
475
            },
            &Instruction_::GetVarPartIRef{is_ptr, base} => {
                let ptr = select!(is_ptr, "PTR", "");
476
                format!("GETVARPARTIREF {} {}", ptr, ops[base])
qinsoon's avatar
qinsoon committed
477
478
479
            },
            
            &Instruction_::Fence(order) => {
480
                format!("FENCE {:?}", order)
qinsoon's avatar
qinsoon committed
481
482
            },
            
483
            &Instruction_::Return(ref vals) => format!("RET {}", op_vector_str(vals, ops)),
qinsoon's avatar
qinsoon committed
484
            &Instruction_::ThreadExit => "THREADEXIT".to_string(),
485
486
487
            &Instruction_::Throw(ref vals) => format!("THROW {}", op_vector_str(vals, ops)),
            &Instruction_::TailCall(ref call) => format!("TAILCALL {}", call.debug_str(ops)),
            &Instruction_::Branch1(ref dest) => format!("BRANCH {}", dest.debug_str(ops)),
qinsoon's avatar
qinsoon committed
488
            &Instruction_::Branch2{cond, ref true_dest, ref false_dest} => {
489
                format!("BRANCH2 {} {} {}", ops[cond], true_dest.debug_str(ops), false_dest.debug_str(ops))
qinsoon's avatar
qinsoon committed
490
491
492
493
            },
            &Instruction_::Watchpoint{id, ref disable_dest, ref resume} => {
                match id {
                    Some(id) => {
494
                        format!("WATCHPOINT {} {} {}", id, disable_dest.as_ref().unwrap().debug_str(ops), resume.debug_str(ops))
qinsoon's avatar
qinsoon committed
495
496
                    },
                    None => {
497
                        format!("TRAP {}", resume.debug_str(ops))
qinsoon's avatar
qinsoon committed
498
499
500
501
                    }
                }
            },
            &Instruction_::WPBranch{wp, ref disable_dest, ref enable_dest} => {
502
                format!("WPBRANCH {} {} {}", wp, disable_dest.debug_str(ops), enable_dest.debug_str(ops))
qinsoon's avatar
qinsoon committed
503
            },
504
            &Instruction_::Call{ref data, ref resume} => format!("CALL {} {}", data.debug_str(ops), resume.debug_str(ops)),
qinsoon's avatar
qinsoon committed
505
            &Instruction_::SwapStack{stack, is_exception, ref args, ref resume} => {
506
                format!("SWAPSTACK {} {} {} {}", ops[stack], is_exception, op_vector_str(args, ops), resume.debug_str(ops))
qinsoon's avatar
qinsoon committed
507
508
            },
            &Instruction_::Switch{cond, ref default, ref branches} => {
509
                let mut ret = format!("SWITCH {} {} {{", ops[cond], default.debug_str(ops));
qinsoon's avatar
qinsoon committed
510
511
                for i in 0..branches.len() {
                    let (op, ref dest) = branches[i];
512
                    ret.push_str(format!("{} {}", ops[op], dest.debug_str(ops)).as_str());
qinsoon's avatar
qinsoon committed
513
514
515
516
517
518
519
520
521
                    if i != branches.len() - 1 {
                        ret.push_str(", ");
                    }
                }
                ret.push_str("}}");
                
                ret
            },
            &Instruction_::ExnInstruction{ref inner, ref resume} => {
522
                format!("{} {}", inner.debug_str(ops), resume.debug_str(ops))
523
524
            }
        }
525
    }    
526
527
}

qinsoon's avatar
qinsoon committed
528
529
530
531
532
533
534
535
536
#[derive(Copy, Clone, Debug)]
pub enum MemoryOrder {
    NotAtomic,
    Relaxed,
    Consume,
    Acquire,
    Release,
    AcqRel,
    SeqCst
537
538
}

qinsoon's avatar
qinsoon committed
539
540
541
542
#[derive(Copy, Clone, Debug)]
pub enum CallConvention {
    Mu,
    Foreign(ForeignFFI)
qinsoon's avatar
qinsoon committed
543
544
}

qinsoon's avatar
qinsoon committed
545
546
547
#[derive(Copy, Clone, Debug)]
pub enum ForeignFFI {
    C
qinsoon's avatar
qinsoon committed
548
549
}

550
#[derive(Clone, Debug)]
qinsoon's avatar
qinsoon committed
551
pub struct CallData {
552
553
    pub func: OpIndex,
    pub args: Vec<OpIndex>,
qinsoon's avatar
qinsoon committed
554
    pub convention: CallConvention
555
556
}

qinsoon's avatar
qinsoon committed
557
558
impl CallData {
    fn debug_str(&self, ops: &Vec<P<TreeNode>>) -> String {
559
        format!("{:?} {} [{}]", self.convention, ops[self.func], op_vector_str(&self.args, ops))
qinsoon's avatar
qinsoon committed
560
561
562
    }
}

563
#[derive(Clone, Debug)]
qinsoon's avatar
qinsoon committed
564
565
566
pub struct ResumptionData {
    pub normal_dest: Destination,
    pub exn_dest: Destination
567
568
}

qinsoon's avatar
qinsoon committed
569
570
impl ResumptionData {
    fn debug_str(&self, ops: &Vec<P<TreeNode>>) -> String {
571
        format!("normal: {}, exception: {}", self.normal_dest.debug_str(ops), self.exn_dest.debug_str(ops))
572
    }
573
574
}

575
#[derive(Clone, Debug)]
qinsoon's avatar
qinsoon committed
576
577
578
pub struct Destination {
    pub target: MuTag,
    pub args: Vec<DestArg>
579
580
}

qinsoon's avatar
qinsoon committed
581
582
impl Destination {
    fn debug_str(&self, ops: &Vec<P<TreeNode>>) -> String {
583
        let mut ret = format!("{}", self.target);
qinsoon's avatar
qinsoon committed
584
585
586
587
588
589
590
591
592
593
594
595
596
597
        ret.push('[');
        for i in 0..self.args.len() {
            let ref arg = self.args[i];
            ret.push_str(arg.debug_str(ops).as_str());
            if i != self.args.len() - 1 {
                ret.push_str(", ");
            }
        }
        ret.push(']');
        
        ret
    }
}

598
#[derive(Clone, Debug)]
599
pub enum DestArg {
600
    Normal(OpIndex),
601
602
603
    Freshbound(usize)
}

qinsoon's avatar
qinsoon committed
604
605
606
impl DestArg {
    fn debug_str(&self, ops: &Vec<P<TreeNode>>) -> String {
        match self {
607
608
            &DestArg::Normal(index) => format!("{}", ops[index]),
            &DestArg::Freshbound(n) => format!("${}", n) 
qinsoon's avatar
qinsoon committed
609
610
611
612
        }
    }
}

613
614
615
616
617
618
619
fn op_vector_str(vec: &Vec<OpIndex>, ops: &Vec<P<TreeNode>>) -> String {
    let mut ret = String::new();
    for i in 0..vec.len() {
        let index = vec[i];
        ret.push_str(format!("{}", ops[index]).as_str());
        if i != vec.len() - 1 {
            ret.push_str(", ");
620
        }
621
622
    }
    ret
qinsoon's avatar
qinsoon committed
623
624
}

625
fn node_vector_str(vec: &Vec<P<TreeNode>>) -> String {
qinsoon's avatar
qinsoon committed
626
627
    let mut ret = String::new();
    for i in 0..vec.len() {
628
        ret.push_str(format!("{}", vec[i]).as_str());
qinsoon's avatar
qinsoon committed
629
630
631
632
633
        if i != vec.len() - 1 {
            ret.push_str(", ");
        }
    }
    ret
634
}