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

inst.rs 64.6 KB
Newer Older
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
1
// Copyright 2017 The Australian National University
2
//
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
3
4
5
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
6
//
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
7
//     http://www.apache.org/licenses/LICENSE-2.0
8
//
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
9
10
11
12
13
14
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

qinsoon's avatar
qinsoon committed
15
use ir::*;
16
use op::*;
qinsoon's avatar
qinsoon committed
17
18
19
use ptr::*;
use types::*;

20
use utils::vec_utils;
21
22
23

use std::fmt;

24
/// Instruction represents a Mu instruction
25
#[derive(Debug, Clone)] // this implements Display
26
pub struct Instruction {
qinsoon's avatar
qinsoon committed
27
    pub hdr: MuEntityHeader,
28
    /// the values this instruction holds
qinsoon's avatar
qinsoon committed
29
    pub value: Option<Vec<P<Value>>>,
30
31
    /// ops field list all the children nodes,
    /// and in Instruction_, the children nodes are referred by indices
32
33
    /// This design makes it easy for the compiler to iterate through all the
    /// children
qinsoon's avatar
qinsoon committed
34
    pub ops: Vec<P<TreeNode>>,
35
    /// used for pattern matching
36
    pub v: Instruction_
37
38
}

39
// Instruction implements MuEntity
qinsoon's avatar
qinsoon committed
40
41
impl_mu_entity!(Instruction);

42
impl Instruction {
43
44
45
46
47
48
49
    pub fn clone_with_id(&self, new_id: MuID) -> Instruction {
        let mut clone = self.clone();
        clone.hdr = self.hdr.clone_with_id(new_id);

        clone
    }

50
51
    // RTMU add new rt instructions to various spec functions here

qinsoon's avatar
qinsoon committed
52
    /// is this instruction the terminal inst of its block?
53
54
    /// Terminal instructions end Mu blocks, and Mu block ends with a terminal
    /// instruction.
55
56
57
58
    pub fn is_terminal_inst(&self) -> bool {
        use inst::Instruction_::*;

        match self.v {
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
            Return(_)
            | ThreadExit
            | Throw(_)
            | TailCall(_)
            | Branch1(_)
            | Branch2 { .. }
            | Watchpoint { .. }
            | WPBranch { .. }
            | Call { .. }
            | CCall { .. }
            | SwapStackExc { .. }
            | SwapStackKill { .. }
            | Switch { .. }
            | ExnInstruction { .. } => true,
            BinOp(_, _, _)
            | BinOpWithStatus(_, _, _, _)
            | CmpOp(_, _, _)
            | ConvOp { .. }
            | ExprCall { .. }
            | ExprCCall { .. }
            | Load { .. }
            | Store { .. }
            | CmpXchg { .. }
            | AtomicRMW { .. }
            | New(_)
            | AllocA(_)
            | NewHybrid(_, _)
            | AllocAHybrid(_, _)
            | NewStack(_)
            | NewThread { .. }
89
            | NewRTThread { .. }
90
            | NewFutex(_)
Javad Ebrahimian Amiri's avatar
Javad Ebrahimian Amiri committed
91
            | DeleteFutex(_)
92
            | LockFutex(_,_)
93
            | UnlockFutex(_,_)
94
95
96
97
98
99
100
            | CondVarNew
            | CondVarDelete(_)
            | CondVarAcqLock(_)
            | CondVarRelLock(_)
            | CondVarWait(_)
            | CondVarSignal(_)
            | CondVarBroadcast(_)
101
            | AllocAU(_)
102
            | AllocAUHybrid(_,_)
103
104
            | NewReg(_)
            | DeleteReg(_)
105
106
107
108
            | Intrinsic_CollectReg(_)
            | Intrinsic_FindReg(_)
            | Intrinsic_GetAllocatedReg(_)
            | Intrinsic_GetFreeReg(_)
109
110
111
112
113
            | rAlloc(_, _)
            | rAllocHybrid(_, _, _)
            | eAlloc(_)
            | eAllocHybrid(_, _)
            | eDelete(_)
114
            | NotifyThread(_)       // TODO remove - not needed anymore
115
116
117
118
119
            | ThreadSetPriority(_,_)
            | ThreadGetPriority(_)
            | ThreadSetCPU(_,_)
            | ThreadClearCPU(_,_)
            | ThreadIssetCPU(_,_)
120
121
            | GetTime
            | SetTime(_)
Javad Ebrahimian Amiri's avatar
Javad Ebrahimian Amiri committed
122
            | NewTimer
123
            | SetTimer { .. }
Javad Ebrahimian Amiri's avatar
Javad Ebrahimian Amiri committed
124
125
126
            | CancelTimer(_)
            | DeleteTimer(_)
            | Sleep(_)
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
            | NewAttr
            | DeleteAttr(_)
            | ThreadSetAttr(_,_)
            | ThreadGetAttr(_)
            | AttrClearCPU(_,_)
            | AttrIssetCPU(_,_)
            | AttrSetCPU(_,_)
            | AttrZeroCPU(_)
            | AttrSetPriority(_,_)
            | AttrGetPriority(_)
            | eAllocPA(_,_)
            | eAllocHybridPA(_,_,_)
            | BindObject(_)
            | UnbindObject(_)
            | NewRegionPA(_,_)
            | BindRegion(_)
            | UnbindRegion(_)
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
            | NewFrameCursor(_)
            | GetIRef(_)
            | GetFieldIRef { .. }
            | GetElementIRef { .. }
            | ShiftIRef { .. }
            | GetVarPartIRef { .. }
            | Select { .. }
            | Fence(_)
            | CommonInst_GetThreadLocal
            | CommonInst_SetThreadLocal(_)
            | CommonInst_Pin(_)
            | CommonInst_Unpin(_)
            | CommonInst_GetAddr(_)
            | CommonInst_Tr64IsFp(_)
            | CommonInst_Tr64IsInt(_)
            | CommonInst_Tr64IsRef(_)
            | CommonInst_Tr64FromFp(_)
            | CommonInst_Tr64FromInt(_)
            | CommonInst_Tr64FromRef(_, _)
            | CommonInst_Tr64ToFp(_)
            | CommonInst_Tr64ToInt(_)
            | CommonInst_Tr64ToRef(_)
            | CommonInst_Tr64ToTag(_)
            | Move(_)
            | PrintHex(_)
169
            | PrintBool(_)
170
            | PrintTime(_)
171
172
173
174
            | SetRetval(_)
            | GetVMThreadLocal
            | KillStack(_)
            | CurrentStack
175
176
            | RandF(_,_)
            | RandI(_,_)
177
            | SwapStackExpr { .. } => false,
178
179
180
        }
    }

qinsoon's avatar
qinsoon committed
181
    /// is this instruction a non-terminal instruction of its block?
182
183
184
185
    pub fn is_non_terminal_inst(&self) -> bool {
        !self.is_terminal_inst()
    }

qinsoon's avatar
qinsoon committed
186
    /// does this instruction has side effect?
187
188
    /// An instruction has side effect if it affects something other than its
    /// result operands. e.g. affecting memory, stack, thread, etc.
189
190
191
192
193
    // FIXME: need to check correctness
    pub fn has_side_effect(&self) -> bool {
        use inst::Instruction_::*;

        match self.v {
194
195
196
197
198
199
200
201
202
203
            ExprCall { .. }
            | ExprCCall { .. }
            | Load { .. }
            | Store { .. }
            | CmpXchg { .. }
            | AtomicRMW { .. }
            | New(_)
            | AllocA(_)
            | NewHybrid(_, _)
            | AllocAHybrid(_, _)
204
            | AllocAU(_)
205
            | AllocAUHybrid(_,_)
206
207
            | NewReg(_)
            | DeleteReg(_)
208
            | Intrinsic_CollectReg(_)
209
210
211
212
213
            | rAlloc(_, _)
            | rAllocHybrid(_,_,_)
            | eAlloc(_)
            | eAllocHybrid(_,_)
            | eDelete(_)
214
215
            | NewStack(_)
            | NewThread { .. }
216
            | NewRTThread { .. }
217
            | NewFutex(_)
Javad Ebrahimian Amiri's avatar
Javad Ebrahimian Amiri committed
218
            | DeleteFutex(_)
219
            | LockFutex(_,_)
220
            | UnlockFutex(_,_)
221
222
223
224
225
226
227
            | CondVarNew
            | CondVarDelete(_)
            | CondVarAcqLock(_)
            | CondVarRelLock(_)
            | CondVarWait(_)
            | CondVarSignal(_)
            | CondVarBroadcast(_)
228
            | NotifyThread(_)
229
230
231
            | ThreadSetPriority(_, _)
            | ThreadClearCPU(_, _)
            | ThreadSetCPU(_, _)
232
233
//            | AffinityZero(_)
            | SetTime(_)
Javad Ebrahimian Amiri's avatar
Javad Ebrahimian Amiri committed
234
            | NewTimer
235
            | SetTimer { .. }
Javad Ebrahimian Amiri's avatar
Javad Ebrahimian Amiri committed
236
237
238
            | CancelTimer(_)
            | DeleteTimer(_)
            | Sleep(_)
239
240
241
242
243
244
245
246
247
248
249
250
251
252
            | NewAttr
            | DeleteAttr(_)
            | ThreadSetAttr(_,_)
            | AttrClearCPU(_,_)
            | AttrSetCPU(_,_)
            | AttrZeroCPU(_)
            | AttrSetPriority(_,_)
            | eAllocPA(_,_)
            | eAllocHybridPA(_,_,_)
            | BindObject(_)
            | UnbindObject(_)
            | NewRegionPA(_,_)
            | BindRegion(_)
            | UnbindRegion(_)
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
            | NewFrameCursor(_)
            | Fence(_)
            | Return(_)
            | ThreadExit
            | Throw(_)
            | TailCall(_)
            | Branch1(_)
            | Branch2 { .. }
            | Watchpoint { .. }
            | WPBranch { .. }
            | Call { .. }
            | CCall { .. }
            | SwapStackExpr { .. }
            | SwapStackExc { .. }
            | SwapStackKill { .. }
            | Switch { .. }
            | ExnInstruction { .. }
            | CommonInst_GetThreadLocal
            | CommonInst_SetThreadLocal(_)
            | CommonInst_Pin(_)
            | CommonInst_Unpin(_)
            | CommonInst_GetAddr(_)
            | PrintHex(_)
276
            | PrintBool(_)
277
            | PrintTime(_)
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
            | SetRetval(_)
            | KillStack(_) => true,
            BinOp(_, _, _)
            | BinOpWithStatus(_, _, _, _)
            | CmpOp(_, _, _)
            | ConvOp { .. }
            | GetIRef(_)
            | GetFieldIRef { .. }
            | GetElementIRef { .. }
            | ShiftIRef { .. }
            | GetVarPartIRef { .. }
            | Select { .. }
            | CommonInst_Tr64IsFp(_)
            | CommonInst_Tr64IsInt(_)
            | CommonInst_Tr64IsRef(_)
            | CommonInst_Tr64FromFp(_)
            | CommonInst_Tr64FromInt(_)
            | CommonInst_Tr64FromRef(_, _)
            | CommonInst_Tr64ToFp(_)
            | CommonInst_Tr64ToInt(_)
            | CommonInst_Tr64ToRef(_)
            | CommonInst_Tr64ToTag(_)
            | Move(_)
            | CurrentStack
302
            | GetVMThreadLocal
303
            | ThreadGetPriority(_)
304
            | GetTime
305
306
307
            | ThreadGetAttr(_)
            | AttrIssetCPU(_,_)
            | AttrGetPriority(_)
308
309
            | RandF(_,_)
            | RandI(_,_)
310
311
312
            | Intrinsic_GetAllocatedReg(_)
            | Intrinsic_GetFreeReg(_)
            | Intrinsic_FindReg(_)
313
            | ThreadIssetCPU(_, _) => false,
314
//            | AffinityEqual(_, _)
315
316
317
        }
    }

qinsoon's avatar
qinsoon committed
318
319
    /// can this instruction throw exception?
    /// an instruction with an exceptional branch can throw exception
320
321
322
323
    pub fn is_potentially_excepting_instruction(&self) -> bool {
        use inst::Instruction_::*;

        match self.v {
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
            Watchpoint { .. }
            | Call { .. }
            | CCall { .. }
            | SwapStackExc { .. }
            | ExnInstruction { .. } => true,
            BinOp(_, _, _)
            | BinOpWithStatus(_, _, _, _)
            | CmpOp(_, _, _)
            | ConvOp { .. }
            | ExprCall { .. }
            | ExprCCall { .. }
            | Load { .. }
            | Store { .. }
            | CmpXchg { .. }
            | AtomicRMW { .. }
            | New(_)
            | AllocA(_)
            | NewHybrid(_, _)
            | AllocAHybrid(_, _)
            | NewStack(_)
344
            | AllocAU(_)
345
            | AllocAUHybrid(_, _)
346
347
            | NewReg(_)
            | DeleteReg(_)
348
349
350
351
            | Intrinsic_CollectReg(_)
            | Intrinsic_FindReg(_)
            | Intrinsic_GetAllocatedReg(_)
            | Intrinsic_GetFreeReg(_)
352
            | rAlloc(_, _)
353
            | rAllocHybrid(_, _, _)
354
            | eAlloc(_)
355
            | eAllocHybrid(_, _)
356
            | eDelete(_)
357
            | NewThread { .. }
358
            | NewRTThread { .. }
359
            | NewFutex(_)
Javad Ebrahimian Amiri's avatar
Javad Ebrahimian Amiri committed
360
            | DeleteFutex(_)
361
            | LockFutex(_, _)
362
            | UnlockFutex(_, _)
363
364
365
366
367
368
369
            | CondVarNew
            | CondVarDelete(_)
            | CondVarAcqLock(_)
            | CondVarRelLock(_)
            | CondVarWait(_)
            | CondVarSignal(_)
            | CondVarBroadcast(_)
370
            | NotifyThread(_)
371
372
373
374
375
            | ThreadSetPriority(_, _)
            | ThreadGetPriority(_)
            | ThreadClearCPU(_, _)
            | ThreadSetCPU(_, _)
            | ThreadIssetCPU(_, _)
376
377
            | GetTime
            | SetTime(_)
Javad Ebrahimian Amiri's avatar
Javad Ebrahimian Amiri committed
378
            | NewTimer
379
            | SetTimer { .. }
Javad Ebrahimian Amiri's avatar
Javad Ebrahimian Amiri committed
380
381
382
            | CancelTimer(_)
            | DeleteTimer(_)
            | Sleep(_)
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
            | NewAttr
            | DeleteAttr(_)
            | ThreadSetAttr(_, _)
            | ThreadGetAttr(_)
            | AttrClearCPU(_, _)
            | AttrIssetCPU(_, _)
            | AttrSetCPU(_, _)
            | AttrZeroCPU(_)
            | AttrSetPriority(_, _)
            | AttrGetPriority(_)
            | eAllocPA(_, _)
            | eAllocHybridPA(_, _, _)
            | BindObject(_)
            | UnbindObject(_)
            | NewRegionPA(_, _)
            | BindRegion(_)
            | UnbindRegion(_)
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
            | NewFrameCursor(_)
            | GetIRef(_)
            | GetFieldIRef { .. }
            | GetElementIRef { .. }
            | ShiftIRef { .. }
            | GetVarPartIRef { .. }
            | Fence(_)
            | Return(_)
            | ThreadExit
            | Throw(_)
            | TailCall(_)
            | Branch1(_)
            | Branch2 { .. }
            | Select { .. }
            | WPBranch { .. }
            | Switch { .. }
            | CommonInst_GetThreadLocal
            | CommonInst_SetThreadLocal(_)
            | CommonInst_Pin(_)
            | CommonInst_Unpin(_)
            | CommonInst_GetAddr(_)
            | CommonInst_Tr64IsFp(_)
            | CommonInst_Tr64IsInt(_)
            | CommonInst_Tr64IsRef(_)
            | CommonInst_Tr64FromFp(_)
            | CommonInst_Tr64FromInt(_)
            | CommonInst_Tr64FromRef(_, _)
            | CommonInst_Tr64ToFp(_)
            | CommonInst_Tr64ToInt(_)
            | CommonInst_Tr64ToRef(_)
            | CommonInst_Tr64ToTag(_)
            | Move(_)
            | PrintHex(_)
433
            | PrintBool(_)
434
            | PrintTime(_)
435
436
437
438
            | SetRetval(_)
            | GetVMThreadLocal
            | KillStack(_)
            | CurrentStack
439
440
            | RandI(_, _)
            | RandF(_, _)
441
            | SwapStackExpr { .. }
442
            | SwapStackKill { .. } => false
443
444
445
        }
    }

qinsoon's avatar
qinsoon committed
446
    /// does this instruction have an exceptional clause/branch?
447
    pub fn has_exception_clause(&self) -> bool {
448
        self.is_potentially_excepting_instruction()
449
450
    }

qinsoon's avatar
qinsoon committed
451
452
    /// returns exception target(block ID),
    /// returns None if this instruction does not have exceptional branch
453
454
455
    pub fn get_exception_target(&self) -> Option<MuID> {
        use inst::Instruction_::*;
        match self.v {
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
            Watchpoint { ref resume, .. }
            | Call { ref resume, .. }
            | CCall { ref resume, .. }
            | SwapStackExc { ref resume, .. }
            | ExnInstruction { ref resume, .. } => Some(resume.exn_dest.target.id()),
            BinOp(_, _, _)
            | BinOpWithStatus(_, _, _, _)
            | CmpOp(_, _, _)
            | ConvOp { .. }
            | ExprCall { .. }
            | ExprCCall { .. }
            | Load { .. }
            | Store { .. }
            | CmpXchg { .. }
            | AtomicRMW { .. }
            | New(_)
            | AllocA(_)
            | NewHybrid(_, _)
474
            | AllocAU(_)
475
            | AllocAUHybrid(_,_)
476
477
            | NewReg(_)
            | DeleteReg(_)
478
479
480
481
            | Intrinsic_CollectReg(_)
            | Intrinsic_FindReg(_)
            | Intrinsic_GetAllocatedReg(_)
            | Intrinsic_GetFreeReg(_)
482
483
484
485
486
487
488
489
            | rAlloc(_, _)
            | rAllocHybrid(_,_,_)
//            | rAllocT(_)
            | eAlloc(_)
            | eAllocHybrid(_,_)
//            | eAllocT(_)
            | eDelete(_)
//            | eDeleteT(_)
490
491
492
            | AllocAHybrid(_, _)
            | NewStack(_)
            | NewThread { .. }
493
            | NewRTThread { .. }
494
            | NewFutex(_)
Javad Ebrahimian Amiri's avatar
Javad Ebrahimian Amiri committed
495
            | DeleteFutex(_)
496
            | LockFutex(_,_)
497
            | UnlockFutex(_,_)
498
499
500
501
502
503
504
            | CondVarNew
            | CondVarDelete(_)
            | CondVarAcqLock(_)
            | CondVarRelLock(_)
            | CondVarWait(_)
            | CondVarSignal(_)
            | CondVarBroadcast(_)
505
            | NotifyThread(_)
506
507
508
            | ThreadSetPriority(_,_)  // FIXME - Not sure about these
            | ThreadGetPriority(_)
            | ThreadClearCPU(_,_)
509
//            | AffinityEqual(_,_)
510
511
            | ThreadIssetCPU(_,_)
            | ThreadSetCPU(_,_)
512
513
514
//            | AffinityZero(_)
            | SetTime(_)
            | GetTime
Javad Ebrahimian Amiri's avatar
Javad Ebrahimian Amiri committed
515
            | NewTimer
516
            | SetTimer { .. }
Javad Ebrahimian Amiri's avatar
Javad Ebrahimian Amiri committed
517
518
519
            | CancelTimer(_)
            | DeleteTimer(_)
            | Sleep(_)
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
            | NewAttr
            | DeleteAttr(_)
            | ThreadSetAttr(_,_)
            | ThreadGetAttr(_)
            | AttrClearCPU(_,_)
            | AttrIssetCPU(_,_)
            | AttrSetCPU(_,_)
            | AttrZeroCPU(_)
            | AttrSetPriority(_,_)
            | AttrGetPriority(_)
            | eAllocPA(_,_)
            | eAllocHybridPA(_,_,_)
            | BindObject(_)
            | UnbindObject(_)
            | NewRegionPA(_,_)
            | BindRegion(_)
            | UnbindRegion(_)
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
            | NewFrameCursor(_)
            | GetIRef(_)
            | GetFieldIRef { .. }
            | GetElementIRef { .. }
            | ShiftIRef { .. }
            | GetVarPartIRef { .. }
            | Fence(_)
            | Return(_)
            | ThreadExit
            | Throw(_)
            | TailCall(_)
            | Branch1(_)
            | Branch2 { .. }
            | Select { .. }
            | WPBranch { .. }
            | Switch { .. }
            | CommonInst_GetThreadLocal
            | CommonInst_SetThreadLocal(_)
            | CommonInst_Pin(_)
            | CommonInst_Unpin(_)
            | CommonInst_GetAddr(_)
            | CommonInst_Tr64IsFp(_)
            | CommonInst_Tr64IsInt(_)
            | CommonInst_Tr64IsRef(_)
            | CommonInst_Tr64FromFp(_)
            | CommonInst_Tr64FromInt(_)
            | CommonInst_Tr64FromRef(_, _)
            | CommonInst_Tr64ToFp(_)
            | CommonInst_Tr64ToInt(_)
            | CommonInst_Tr64ToRef(_)
            | CommonInst_Tr64ToTag(_)
            | Move(_)
            | PrintHex(_)
570
            | PrintBool(_)
571
            | PrintTime(_)
572
573
574
575
            | SetRetval(_)
            | GetVMThreadLocal
            | KillStack(_)
            | CurrentStack
576
577
            | RandF(_,_)
            | RandI(_,_)
578
579
            | SwapStackExpr { .. }
            | SwapStackKill { .. } => None,
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
609
610
611
612
613
614
615
    /// can this instruction throw exception?
    /// (whether or not it containjs a ctach for it)
    pub fn is_potentially_throwing(&self) -> bool {
        use inst::Instruction_::*;

        match self.v {
            // Note: commented out ones are ones where we haven't implemented exceptions yet
            Watchpoint { .. } |
            Call { .. } |
            CCall { .. } |
            SwapStackExc { .. } |
            SwapStackExpr { .. } |
            ExnInstruction { .. } |
            ExprCall { .. } |
            ExprCCall { .. } |
            //Load { .. } |
            //Store { .. } |
            //CmpXchg { .. } |
            //AtomicRMW { .. } |
            //New(_) |
            //NewHybrid(_, _) |
            Throw(_)  => true,

            // BinOp(op, _, _) |
            // BinOpWithStatus(op, _, _, _) if op.may_throw() => true,
            BinOp(_, _, _) |
            BinOpWithStatus(_, _, _, _) |
            CmpOp(_, _, _) |
            ConvOp { .. } |
            AllocA(_) |
            AllocAHybrid(_, _) |
            NewStack(_) |
            NewThread { .. } |
616
            NewRTThread { .. } |
617
            NewFutex(_)
Javad Ebrahimian Amiri's avatar
Javad Ebrahimian Amiri committed
618
            | DeleteFutex(_)
619
            | LockFutex(_,_)
620
            | UnlockFutex(_,_)
621
622
623
624
625
626
627
            | CondVarNew
            | CondVarDelete(_)
            | CondVarAcqLock(_)
            | CondVarRelLock(_)
            | CondVarWait(_)
            | CondVarSignal(_)
            | CondVarBroadcast(_)
Javad Ebrahimian Amiri's avatar
Javad Ebrahimian Amiri committed
628
            | NotifyThread(_) |
629
            ThreadSetPriority(_,_) |
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
660
661
            NewFrameCursor(_) |
            GetIRef(_) |
            GetFieldIRef { .. } |
            GetElementIRef { .. } |
            ShiftIRef { .. } |
            GetVarPartIRef { .. } |
            Fence(_) |
            Return(_) |
            ThreadExit |
            TailCall(_) |
            Branch1(_) |
            Branch2 { .. } |
            Select { .. } |
            WPBranch { .. } |
            Switch { .. } |
            CommonInst_GetThreadLocal |
            CommonInst_SetThreadLocal(_) |
            CommonInst_Pin(_) |
            CommonInst_Unpin(_) |
            CommonInst_GetAddr(_) |
            CommonInst_Tr64IsFp(_) |
            CommonInst_Tr64IsInt(_) |
            CommonInst_Tr64IsRef(_) |
            CommonInst_Tr64FromFp(_) |
            CommonInst_Tr64FromInt(_) |
            CommonInst_Tr64FromRef(_, _) |
            CommonInst_Tr64ToFp(_) |
            CommonInst_Tr64ToInt(_) |
            CommonInst_Tr64ToRef(_) |
            CommonInst_Tr64ToTag(_) |
            Move(_) |
            PrintHex(_) |
662
            PrintBool(_) |
663
            PrintTime(_) |
664
            SetRetval(_) |
qinsoon's avatar
qinsoon committed
665
            GetVMThreadLocal |
666
667
668
669
670
671
672
673
            KillStack(_) |
            CurrentStack |
            SwapStackKill { .. } => false,

            _ => false
        }
    }

674
    fn debug_str(&self, ops: &Vec<P<TreeNode>>) -> String {
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
675
676
677
678
        match &self.v {
            &Instruction_::BinOp(op, op1, op2) => {
                format!("{}<{}> {} {}", op, ops[op1].ty(), ops[op1], ops[op2])
            }
679
680
681
682
683
684
685
686
            &Instruction_::BinOpWithStatus(op, status, op1, op2) => format!(
                "{}{}<{}> {} {}",
                op,
                status,
                ops[op1].ty(),
                ops[op1],
                ops[op2]
            ),
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
687
688
689
690
691
692
693
            &Instruction_::CmpOp(op, op1, op2) => {
                format!("{}<{}> {} {}", op, ops[op1].ty(), ops[op1], ops[op2])
            }
            &Instruction_::ConvOp {
                operation,
                ref from_ty,
                ref to_ty,
694
695
696
697
698
                operand
            } => format!(
                "{} <{} {}> {}",
                operation, from_ty, to_ty, ops[operand]
            ),
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
            &Instruction_::ExprCall { ref data, is_abort } => {
                if is_abort {
                    panic!("ABORT is not supported");
                }
                format!("CALL{}", data.debug_str(ops))
            }
            &Instruction_::ExprCCall { ref data, is_abort } => {
                if is_abort {
                    panic!("ABORT is not supported");
                }
                format!("CCALL{}", data.debug_str(ops))
            }
            &Instruction_::Load {
                is_ptr,
                mem_loc,
714
                order
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
715
716
717
718
719
720
721
722
723
724
725
726
727
728
            } => {
                let ptr = select_value!(is_ptr, " PTR", "");
                format!(
                    "LOAD{} {}<{}> {}",
                    ptr,
                    order,
                    ops[mem_loc].ty().get_referent_ty().unwrap(),
                    ops[mem_loc]
                )
            }
            &Instruction_::Store {
                value,
                is_ptr,
                mem_loc,
729
                order
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
            } => {
                let ptr = select_value!(is_ptr, " PTR", "");
                format!(
                    "STORE{} {}<{}> {} {}",
                    ptr,
                    order,
                    ops[mem_loc].ty().get_referent_ty().unwrap(),
                    ops[mem_loc],
                    ops[value]
                )
            }
            &Instruction_::CmpXchg {
                is_ptr,
                is_weak,
                success_order,
                fail_order,
                mem_loc,
                expected_value,
748
                desired_value
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
            } => {
                let ptr = select_value!(is_ptr, " PTR", "");
                let weak = select_value!(is_weak, " WEAK", "");
                format!(
                    "CMPXCHG{}{} {} {}<{}> {} {} {}",
                    ptr,
                    weak,
                    success_order,
                    fail_order,
                    ops[mem_loc].ty().get_referent_ty().unwrap(),
                    ops[mem_loc],
                    ops[expected_value],
                    ops[desired_value]
                )
            }
            &Instruction_::AtomicRMW {
                is_ptr,
                order,
                op,
                mem_loc,
769
                value
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
            } => {
                let ptr = select_value!(is_ptr, " PTR", "");
                format!(
                    "ATOMICRMW{} {} {}<{}> {} {}",
                    ptr,
                    order,
                    op,
                    ops[mem_loc].ty().get_referent_ty().unwrap(),
                    ops[mem_loc],
                    ops[value]
                )
            }
            &Instruction_::New(ref ty) => format!("NEW<{}>", ty),
            &Instruction_::AllocA(ref ty) => format!("ALLOCA<{}>", ty),
            &Instruction_::NewHybrid(ref ty, len) => {
                format!("NEWHYBRID<{} {}> {}", ty, ops[len].ty(), ops[len])
            }
            &Instruction_::AllocAHybrid(ref ty, len) => {
                format!("ALLOCAHYBRID<{} {}> {}", ty, ops[len].ty(), ops[len])
            }
790
791
792
793
794
            &Instruction_::NewStack(func) => format!(
                "COMMINST @uvm.new_stack<[{}]>({})",
                ops[func].ty().get_sig().unwrap(),
                ops[func]
            ),
795
796
797
798
799
800
            &Instruction_::NewReg(size) => {
                format!("COMMINST @uvm.new_region({})", ops[size])
            }
            &Instruction_::DeleteReg(regref) => {
                format!("COMMINST @uvm.delete_region({})", ops[regref])
            }
801
802
803
804
805
806
807
808
809
810
811
812
            &Instruction_::Intrinsic_CollectReg(regref) => {
                format!("INTRINSIC @uvm.collect_region({})", ops[regref])
            }
            &Instruction_::Intrinsic_FindReg(regref) => {
                format!("INTRINSIC @uvm.find_region({})", ops[regref])
            }
            &Instruction_::Intrinsic_GetAllocatedReg(regref) => {
                format!("INTRINSIC @uvm.get_allocated_region({})", ops[regref])
            }
            &Instruction_::Intrinsic_GetFreeReg(regref) => {
                format!("INTRINSIC @uvm.get_free_region({})", ops[regref])
            }
813
814
815
            &Instruction_::AllocAU(ref ty) => {
                format!("COMMINST @uvm.AllocAU({})", ty.id())
            }
816
817
818
819
820
            &Instruction_::AllocAUHybrid(ref ty, var_len) => format!(
                "COMMINST @uvm.AllocAUHybrid({}, {})",
                ty.id(),
                ops[var_len]
            ),
821
822
823
            &Instruction_::rAlloc(regref, ref ty) => {
                format!("COMMINST @uvm.rAlloc({}, {})", ops[regref], ty.id())
            }
824
825
826
827
828
829
            &Instruction_::rAllocHybrid(regref, ref ty, var_len) => format!(
                "COMMINST @uvm.rAllocHybrid({}, {}, {})",
                ops[regref],
                ty.id(),
                ops[var_len]
            ),
830
831
832
833
834
835
836
            //            &Instruction_::rAllocT(regref, ty) => format!(
            //                "COMMINST @uvm.rAllocT({}, {})",
            //                ops[regref],
            //                ops[ty]
            //            ),
            &Instruction_::eAlloc(ref ty) => {
                format!("COMMINST @uvm.eAlloc({})", ty.id())
837
            }
838
            &Instruction_::eAllocHybrid(ref ty, var_len) => format!(
839
840
841
842
                "COMMINST @uvm.eAllocHybrid({}, {})",
                ty.id(),
                ops[var_len]
            ),
843
844
845
846
847
848
            //            &Instruction_::eAllocT( ty) => format!(
            //                "COMMINST @uvm.eAllocT({})",
            //                ops[ty]
            //            ),
            &Instruction_::eDelete(obj) => {
                format!("COMMINST @uvm.eDelete({})", ops[obj])
849
            }
850
851
852
853
            //            &Instruction_::eDeleteT( obj) => format!(
            //                "COMMINST @uvm.eDeleteT({})",
            //                ops[obj]
            //            ),
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
854
855
856
857
            &Instruction_::NewThread {
                stack,
                thread_local,
                is_exception,
858
                ref args
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
859
            } => {
860
861
                let new_stack_clause =
                    format_new_stack_clause(is_exception, args, ops);
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
862
863
864
865
                let thread_local = thread_local
                    .map(|t| format!(" THREADLOCAL({})", ops[t]))
                    .unwrap_or("".to_string());
                format!(
866
                    "NEWTHREAD {}{} {}",
867
                    ops[stack], thread_local, new_stack_clause,
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
868
                )
869
            }
Javad Ebrahimian Amiri's avatar
Javad Ebrahimian Amiri committed
870

871
872
873
            &Instruction_::NewFutex(init_val) => {
                format!("NEWFUTEX {}", ops[init_val])
            }
Javad Ebrahimian Amiri's avatar
Javad Ebrahimian Amiri committed
874
            &Instruction_::DeleteFutex(futexref) => {
875
876
877
878
879
                format!("DELETEFUTEX {}", ops[futexref])
            }
            &Instruction_::LockFutex(futexref, timeout) => {
                format!("LockFUTEX ({}, {})", ops[futexref], ops[timeout])
            }
880
881
            &Instruction_::UnlockFutex(futexref, count) => {
                format!("UNLOCKFUTEX {}, {}", ops[futexref], ops[count])
882
            }
883

884
            &Instruction_::CondVarNew => format!("CONDVAR_NEW"),
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
            &Instruction_::CondVarDelete(addr) => {
                format!("CONDVAR_DELETE {}", ops[addr])
            }
            &Instruction_::CondVarAcqLock(addr) => {
                format!("CONDVAR_ACQ_LOCK {}", ops[addr])
            }
            &Instruction_::CondVarRelLock(addr) => {
                format!("CONDVAR_REL_LOCK {}", ops[addr])
            }
            &Instruction_::CondVarWait(addr) => {
                format!("CONDVAR_WAIT {}", ops[addr])
            }
            &Instruction_::CondVarSignal(addr) => {
                format!("CONDVAR_SIGNAL {}", ops[addr])
            }
            &Instruction_::CondVarBroadcast(addr) => {
                format!("CONDVAR_BROADCAST {}", ops[addr])
            }

904
905
906
907
908
            &Instruction_::NewRTThread {
                attr,
                stack,
                thread_local,
                is_exception,
909
                ref args
910
            } => {
911
912
                let new_stack_clause =
                    format_new_stack_clause(is_exception, args, ops);
913
914
915
916
917
918
919
                let thread_local = thread_local
                    .map(|t| format!(" THREADLOCAL({})", ops[t]))
                    .unwrap_or("".to_string());
                format!(
                    "NEWRTTHREAD {}, {}, {}, {}",
                    ops[attr], ops[stack], thread_local, new_stack_clause,
                )
920
            }
921

922
923
            &Instruction_::NotifyThread(thread) => {
                format!("COMMINST @uvm.notifythread({})", ops[thread])
924
925
926
            }
            &Instruction_::ThreadSetPriority(thread, priority) => format!(
                "COMMINST @uvm.threadsetpriority({}, {})",
927
928
                ops[thread], ops[priority]
            ),
929
930
            &Instruction_::ThreadGetPriority(thread) => {
                format!("COMMINST @uvm.threadgetpriority({})", ops[thread])
931
            }
932
933
            &Instruction_::ThreadClearCPU(thread, cpu) => format!(
                "COMMINST @uvm.threadclearcpu({}, {})",
934
935
                ops[thread], ops[cpu]
            ),
936
937
            &Instruction_::ThreadSetCPU(thread, cpu) => format!(
                "COMMINST @uvm.threadsetcpu({}, {})",
938
939
                ops[thread], ops[cpu]
            ),
940
941
            &Instruction_::ThreadIssetCPU(thread, cpu) => format!(
                "COMMINST @uvm.threadissetcpu({}, {})",
942
943
                ops[thread], ops[cpu]
            ),
944
945
946
947
948
            &Instruction_::GetTime => format!("COMMINST @uvm.gettime()",),
            &Instruction_::SetTime(time) => {
                format!("COMMINST @uvm.settime({})", ops[time])
            }
            &Instruction_::NewTimer => format!("COMMINST @uvm.newtimer"),
949
950
951
952
953
954
            &Instruction_::SetTimer {
                tmr,
                tm,
                prd,
                ref data
            } => format!(
955
956
                "COMMINST @uvm.settimer({}, {}, {}) ",
                ops[tmr], ops[tm], ops[prd]
957
            ),
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
            &Instruction_::CancelTimer(tmr) => {
                format!("COMMINST @uvm.canceltimer({})", ops[tmr])
            }
            &Instruction_::DeleteTimer(tmr) => {
                format!("COMMINST @uvm.deletetimer({})", ops[tmr])
            }
            &Instruction_::Sleep(dur) => {
                format!("COMMINST @uvm.sleep_ns({})", ops[dur])
            }

            &Instruction_::NewAttr => format!("NEWATTR()"),
            &Instruction_::DeleteAttr(aref) => {
                format!("DELETEATTR({})", ops[aref])
            }
            &Instruction_::ThreadSetAttr(tref, aref) => {
                format!("SETATTR({}, {})", ops[tref], ops[aref])
            }
            &Instruction_::ThreadGetAttr(tref) => {
                format!("GETATTR({})", ops[tref])
            }
            &Instruction_::AttrSetPriority(aref, p) => format!(
                "COMMINST @uvm.attr.setpriority({}, {})",
                ops[aref], ops[p]
981
            ),
982
983
984
985
986
987
988
989
990
            &Instruction_::AttrGetPriority(aref) => {
                format!("COMMINST @uvm.attr.getpriority({})", ops[aref])
            }
            &Instruction_::AttrSetCPU(aref, c) => {
                format!("COMMINST @uvm.attr.setcpu({}, {})", ops[aref], ops[c])
            }
            &Instruction_::AttrClearCPU(aref, c) => format!(
                "COMMINST @uvm.attr.clearcpu({}, {})",
                ops[aref], ops[c]
Javad Ebrahimian Amiri's avatar
Javad Ebrahimian Amiri committed
991
            ),
992
993
994
            &Instruction_::AttrIssetCPU(aref, c) => format!(
                "COMMINST @uvm.attr.issetcpu({}, {})",
                ops[aref], ops[c]
Javad Ebrahimian Amiri's avatar
Javad Ebrahimian Amiri committed
995
            ),
996
997
998
999
1000
1001
1002
            &Instruction_::AttrZeroCPU(aref) => {
                format!("COMMINST @uvm.attr.zerocpu({})", ops[aref])
            }
            &Instruction_::eAllocPA(ref ty, addr) => format!(
                "COMMINST @uvm.emm.eallocpa({}, {})",
                ty.id(),
                ops[addr]
Javad Ebrahimian Amiri's avatar
Javad Ebrahimian Amiri committed
1003
            ),
1004
1005
1006
1007
1008
            &Instruction_::eAllocHybridPA(ref ty, len, addr) => format!(
                "COMMINST @uvm.emm.eallochybridpa({}, {}, {})",
                ty.id(),
                ops[len],
                ops[addr]
Javad Ebrahimian Amiri's avatar
Javad Ebrahimian Amiri committed
1009
            ),
1010
1011
1012
1013
1014
1015
1016
1017
1018
            &Instruction_::BindObject(obj) => {
                format!("COMMINST @uvm.emm.bindobject({})", ops[obj])
            }
            &Instruction_::UnbindObject(obj) => {
                format!("COMMINST @uvm.emm.unbindobject({})", ops[obj])
            }
            &Instruction_::NewRegionPA(size, addr) => format!(
                "COMMINST @uvm.regions.newregionpa({}, {})",
                ops[size], ops[addr]
Javad Ebrahimian Amiri's avatar
Javad Ebrahimian Amiri committed
1019
            ),
1020
1021
1022
1023
1024
1025
1026
            &Instruction_::BindRegion(reg) => {
                format!("COMMINST @uvm.regions.bindregion({})", ops[reg])
            }
            &Instruction_::UnbindRegion(reg) => {
                format!("COMMINST @uvm.regions.unbindregion({})", ops[reg])
            }

Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
1027
1028
1029
            &Instruction_::NewFrameCursor(stack) => {
                format!("COMMINST @uvm.meta.new_cursor({})", ops[stack])
            }
1030
1031
1032
1033
1034
            &Instruction_::GetIRef(reference) => format!(
                "GETIREF<{}> {}",
                ops[reference].ty().get_referent_ty().unwrap(),
                ops[reference]
            ),
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
1035
1036
1037
            &Instruction_::GetFieldIRef {
                is_ptr,
                base,
1038
                index
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
            } => {
                let ptr = select_value!(is_ptr, " PTR", "");
                format!(
                    "GETFIELDIREF{}<{} {}> {}",
                    ptr,
                    ops[base].ty().get_referent_ty().unwrap(),
                    index,
                    ops[base]
                )
            }
            &Instruction_::GetElementIRef {
                is_ptr,
                base,
1052
                index
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
            } => {
                let ptr = select_value!(is_ptr, " PTR", "");
                format!(
                    "GETELEMIREF{}<{} {}>{} {}",
                    ptr,
                    ops[base].ty().get_referent_ty().unwrap(),
                    ops[index].ty(),
                    ops[base],
                    ops[index]
                )
            }
            &Instruction_::ShiftIRef {
                is_ptr,
                base,
1067
                offset
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
1068
1069
1070
            } => {
                let ptr = select_value!(is_ptr, " PTR", "");
                format!(
1071
                    "SHIFTIREF{}<{} {}>{} {}",
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano 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
1096
1097
1098
1099
                    ptr,
                    ops[base].ty().get_referent_ty().unwrap(),
                    ops[offset].ty(),
                    ops[base],
                    ops[offset]
                )
            }
            &Instruction_::GetVarPartIRef { is_ptr, base } => {
                let ptr = select_value!(is_ptr, " PTR", "");
                format!(
                    "GETVARPARTIREF{}<{}> {}",
                    ptr,
                    ops[base].ty().get_referent_ty().unwrap(),
                    ops[base]
                )
            }

            &Instruction_::Fence(order) => format!("FENCE {}", order),

            &Instruction_::Return(ref vals) => {
                if vals.len() == 0 {
                    format!("RET")
                } else if vals.len() == 1 {
                    format!("RET {}", ops[vals[0]])
                } else {
                    format!("RET ({})", op_vector_str(vals, ops))
                }
            }
1100
1101
1102
1103
1104
1105
1106
1107
1108
            &Instruction_::ThreadExit => {
                "COMMINST @uvm.thread_exit".to_string()
            }
            &Instruction_::CurrentStack => {
                "COMMINST @uvm.current_stack".to_string()
            }
            &Instruction_::KillStack(s) => {
                format!("COMMINST @uvm.kill_stack({})", ops[s])
            }
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
1109
            &Instruction_::Throw(exn_obj) => format!("THROW {}", ops[exn_obj]),
1110
1111
1112
1113
1114
1115
            &Instruction_::TailCall(ref call) => {
                format!("TAILCALL{}", call.debug_str(ops))
            }
            &Instruction_::Branch1(ref dest) => {
                format!("BRANCH {}", dest.debug_str(ops))
            }
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
1116
1117
1118
1119
1120
            &Instruction_::Branch2 {
                cond,
                ref true_dest,
                ref false_dest,
                ..
1121
1122
1123
1124
1125
1126
            } => format!(
                "BRANCH2 {} {} {}",
                ops[cond],
                true_dest.debug_str(ops),
                false_dest.debug_str(ops)
            ),
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
1127
1128
1129
            &Instruction_::Select {
                cond,
                true_val,
1130
                false_val
1131
1132
1133
1134
1135
1136
1137
1138
            } => format!(
                "SELECT<{} {}> {} {} {}",
                ops[cond].ty(),
                ops[true_val].ty(),
                ops[cond],
                ops[true_val],
                ops[false_val]
            ),
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
1139
1140
1141
            &Instruction_::Watchpoint {
                id,
                ref disable_dest,
1142
                ref resume
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
            } => {
                match id {
                    Some(id) => {
                        format!(
                            // TODO: WPEXC should be optional
                            "WATCHPOINT {}<{}> {} {} WPEXC({})",
                            id,
                            format_value_types(&self.value),
                            disable_dest.as_ref().unwrap().debug_str(ops),
                            resume.normal_dest.debug_str(ops),
                            resume.exn_dest.debug_str(ops)
                        )
                    }
                    //TRAP < Ts > excClause keepAliveClause
1157
1158
1159
1160
                    None => format!(
                        "TRAP<{}> {}",
                        format_value_types(&self.value),
                        resume.debug_str(ops)
1161
                    )
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
1162
1163
1164
1165
1166
                }
            }
            &Instruction_::WPBranch {
                wp,
                ref disable_dest,
1167
                ref enable_dest
1168
1169
1170
1171
1172
1173
            } => format!(
                "WPBRANCH {} {} {}",
                wp,
                disable_dest.debug_str(ops),
                enable_dest.debug_str(ops)
            ),
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
1174
1175
            &Instruction_::Call {
                ref data,
1176
1177
1178
1179
                ref resume
            } => {
                format!("CALL{} {}", data.debug_str(ops), resume.debug_str(ops))
            }
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
1180
1181
            &Instruction_::CCall {
                ref data,
1182
1183
1184
1185
1186
1187
                ref resume
            } => format!(
                "CCALL{} {}",
                data.debug_str(ops),
                resume.debug_str(ops)
            ),
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
1188
1189
1190
            &Instruction_::SwapStackExpr {
                stack,
                is_exception,
1191
                ref args
1192
1193
1194
1195
1196
1197
            } => format!(
                "SWAPSTACK {} RET_WITH<{}> {}",
                ops[stack],
                format_value_types(&self.value),
                format_new_stack_clause(is_exception, args, ops)
            ),
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
1198
1199
1200
1201
            &Instruction_::SwapStackExc {
                stack,
                is_exception,
                ref args,
1202
                ref resume
1203
1204
1205
1206
1207
1208
1209
            } => format!(
                "SWAPSTACK {} RET_WITH<{}> {} {}",
                ops[stack],
                format_value_types(&self.value),
                format_new_stack_clause(is_exception, args, ops),
                resume.debug_str(ops)
            ),
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
1210
1211
1212
1213

            &Instruction_::SwapStackKill {
                stack,
                is_exception,
1214
                ref args
1215
1216
1217
1218
1219
            } => format!(
                "SWAPSTACK {} KILL_OLD {}",
                ops[stack],
                format_new_stack_clause(is_exception, args, ops)
            ),
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
1220
1221
1222
1223

            &Instruction_::Switch {
                cond,
                ref default,
1224
                ref branches
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
            } => {
                //SWITCH < T > opnd default { ( value dest ) rep }
                let mut ret = format!(
                    "SWITCH<{}> {} {} {{",
                    ops[cond].ty(),
                    ops[cond],
                    default.debug_str(ops)
                );
                for i in 0..branches.len() {
                    let (op, ref dest) = branches[i];
1235
1236
1237
                    ret.push_str(
                        format!("{} {}", ops[op], dest.debug_str(ops)).as_str()
                    );
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
1238
1239
1240
1241
                    if i != branches.len() - 1 {
                        ret.push_str(" ");
                    }
                }
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
1242
                ret.push_str("}");
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
1243
1244
1245
1246
1247

                ret
            }
            &Instruction_::ExnInstruction {
                ref inner,
1248
                ref resume
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
1249
1250
1251
            } => format!("{} {}", inner.debug_str(ops), resume.debug_str(ops)),

            // common inst
1252
1253
1254
            &Instruction_::CommonInst_GetThreadLocal => {
                format!("COMMINST @uvm.get_threadlocal")
            }
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
1255
1256
1257
1258
            &Instruction_::CommonInst_SetThreadLocal(op) => {
                format!("COMMINST @uvm.set_threadlocal({})", ops[op])
            }

1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
            &Instruction_::CommonInst_Pin(op) => format!(
                "COMMINST @uvm.native.pin<{}>({})",
                ops[op].ty(),
                ops[op]
            ),
            &Instruction_::CommonInst_Unpin(op) => format!(
                "COMMINST @uvm.native.unpin<{}>({})",
                ops[op].ty(),
                ops[op]
            ),
1269
1270
1271
1272
1273
            &Instruction_::CommonInst_GetAddr(op) => format!(
                "COMMINST @uvm.native.get_addr<{}>({})",
                ops[op].ty(),
                ops[op]
            ),
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
            // Tagerf64
            &Instruction_::CommonInst_Tr64IsFp(op) => {
                format!("COMMINST @uvm.tr64.is_fp({})", ops[op])
            }
            &Instruction_::CommonInst_Tr64IsInt(op) => {
                format!("COMMINST @uvm.tr64.is_int({})", ops[op])
            }
            &Instruction_::CommonInst_Tr64IsRef(op) => {
                format!("COMMINST @uvm.tr64.is_ref({})", ops[op])
            }
            &Instruction_::CommonInst_Tr64FromFp(op) => {
                format!("COMMINST @uvm.tr64.from_fp({})", ops[op])
            }
            &Instruction_::CommonInst_Tr64FromInt(op) => {
                format!("COMMINST @uvm.tr64.from_int({})", ops[op])
            }
1290
1291
1292
1293
            &Instruction_::CommonInst_Tr64FromRef(op1, op2) => format!(
                "COMMINST @uvm.tr64.from_ref({} {})",
                ops[op1], ops[op2]
            ),
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
            &Instruction_::CommonInst_Tr64ToFp(op) => {
                format!("COMMINST @uvm.tr64.to_fp({})", ops[op])
            }
            &Instruction_::CommonInst_Tr64ToInt(op) => {
                format!("COMMINST @uvm.tr64.to_int({})", ops[op])
            }
            &Instruction_::CommonInst_Tr64ToRef(op) => {
                format!("COMMINST @uvm.tr64.to_ref({})", ops[op])
            }
            &Instruction_::CommonInst_Tr64ToTag(op) => {
                format!("COMMINST @uvm.tr64.to_tag({})", ops[op])
            }

            // move
1308
1309
1310
            &Instruction_::Move(from) => {
                format!("MOVE<{}> {}", ops[from].ty(), ops[from])
            }
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
1311
            // print hex
1312
1313
1314
1315
1316
1317
            &Instruction_::PrintHex(i) => {
                format!("PRINTHEX<{}> {}", ops[i].ty(), ops[i])
            }
            &Instruction_::PrintBool(i) => {
                format!("PRINTBOOL<{}> {}", ops[i].ty(), ops[i])
            }
1318
1319
1320
            &Instruction_::PrintTime(i) => {
                format!("PRINTTIME<{}> {}", ops[i].ty(), ops[i])
            }
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
1321
            // set retval
qinsoon's avatar
qinsoon committed
1322
            &Instruction_::SetRetval(val) => format!("SETRETVAL {}", ops[val]),
1323
1324
1325
1326
1327
1328
            &Instruction_::RandI(min, max) => {
                format!("RandI ({}, {})", ops[min], ops[max])
            }
            &Instruction_::RandF(min, max) => {
                format!("RandF ({}, {})", ops[min], ops[max])
            }
qinsoon's avatar
qinsoon committed
1329
            // get vm thread local
1330
            &Instruction_::GetVMThreadLocal => format!("GETVMTHREADLOCAL")
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
1331
        }
1332
1333
1334
    }
}

1335
1336
const PRINT_INST_NAME: bool = false;

1337
1338
impl fmt::Display for Instruction {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1339
        let ref ops = self.ops;
1340
        let value = match &self.value {
1341
1342
1343
            &Some(ref v) if v.len() == 0 => format!(""),
            &Some(ref v) if v.len() == 1 => format!("{} = ", v[0]),
            &Some(ref v) => format!("({}) = ", vec_utils::as_str_sp(&v)),
1344
            &None => format!("")
1345
1346
1347
        };

        if PRINT_INST_NAME {
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
1348
            write!(f, "{}[{}]{}", value, self.hdr, self.debug_str(ops))