ir_macros.rs 21.7 KB
Newer Older
1
macro_rules! typedef {
qinsoon's avatar
qinsoon committed
2
    // int, floating point
3
    (($vm: expr) $name: ident = mu_int($len: expr)) => {
4 5
        let $name = $vm.declare_type(MuEntityHeader::named($vm.next_id(), Mu(stringify!($name))), MuType_::int($len));
        $vm.set_name($name.as_entity());
6
    };
qinsoon's avatar
qinsoon committed
7
    (($vm: expr) $name: ident = mu_double) => {
8 9
        let $name = $vm.declare_type(MuEntityHeader::named($vm.next_id(), Mu(stringify!($name))), MuType_::double());
        $vm.set_name($name.as_entity());
qinsoon's avatar
qinsoon committed
10
    };
11 12 13 14
    (($vm: expr) $name: ident = mu_float) => {
        let $name = $vm.declare_type(MuEntityHeader::named($vm.next_id(), Mu(stringify!($name))), MuType_::float());
        $vm.set_name($name.as_entity());
    };
qinsoon's avatar
qinsoon committed
15

qinsoon's avatar
qinsoon committed
16
    // ref, iref, ptr
17
    (($vm: expr) $name: ident = mu_ref($ty: ident)) => {
18 19
        let $name = $vm.declare_type(MuEntityHeader::named($vm.next_id(), Mu(stringify!($name))), MuType_::muref($ty.clone()));
        $vm.set_name($name.as_entity());
20 21
    };
    (($vm: expr) $name: ident = mu_iref($ty: ident)) => {
22 23
        let $name = $vm.declare_type(MuEntityHeader::named($vm.next_id(), Mu(stringify!($name))), MuType_::iref($ty.clone()));
        $vm.set_name($name.as_entity());
24
    };
qinsoon's avatar
qinsoon committed
25
    (($vm: expr) $name: ident = mu_uptr($ty: ident)) => {
26 27
        let $name = $vm.declare_type(MuEntityHeader::named($vm.next_id(), Mu(stringify!($name))), MuType_::uptr($ty.clone()));
        $vm.set_name($name.as_entity());
qinsoon's avatar
qinsoon committed
28 29
    };

qinsoon's avatar
qinsoon committed
30
    // struct
31
    (($vm: expr) $name: ident = mu_struct($($ty: ident), *)) => {
32 33
        let $name = $vm.declare_type(MuEntityHeader::named($vm.next_id(), Mu(stringify!($name))), MuType_::mustruct(Mu(stringify!($name)), vec![$($ty.clone()),*]));
        $vm.set_name($name.as_entity());
34
    };
qinsoon's avatar
qinsoon committed
35
    (($vm: expr) $name: ident = mu_struct()) => {
36 37
        let $name = $vm.declare_type(MuEntityHeader::named($vm.next_id(), Mu(stringify!($name))), MuType_::mustruct(Mu(stringify!($name)), vec![]));
        $vm.set_name($name.as_entity());
qinsoon's avatar
qinsoon committed
38
    };
qinsoon's avatar
qinsoon committed
39
    (($vm: expr) $name: ident = mu_struct_placeholder()) => {
40 41
        let $name = $vm.declare_type(MuEntityHeader::named($vm.next_id(), Mu(stringify!($name))), MuType_::mustruct_empty(Mu(stringify!($name))));
        $vm.set_name($name.as_entity());
qinsoon's avatar
qinsoon committed
42 43 44 45
    };
    (($vm: expr) mu_struct_put($name: ident, $($ty: ident), *)) => {
        MuType_::mustruct_put(&Mu(stringify!($name)), vec![$($ty.clone()), *])
    };
qinsoon's avatar
qinsoon committed
46

qinsoon's avatar
qinsoon committed
47
    // hybrid
48 49 50
    (($vm: expr) $name: ident = mu_hybrid($($ty: ident), *)($var_ty: ident)) => {
        let $name = $vm.declare_type(MuEntityHeader::named($vm.next_id(), Mu(stringify!($name))), MuType_::hybrid(Mu(stringify!($name)), vec![$($ty.clone()), *], $var_ty.clone()));
        $vm.set_name($name.as_entity());
qinsoon's avatar
qinsoon committed
51
    };
qinsoon's avatar
qinsoon committed
52

qinsoon's avatar
fix  
qinsoon committed
53
    // array
54
    (($vm: expr) $name: ident = mu_array($ty: ident, $len: expr)) => {
55 56
        let $name = $vm.declare_type(MuEntityHeader::named($vm.next_id(), Mu(stringify!($name))), MuType_::array($ty.clone(), $len));
        $vm.set_name($name.as_entity());
57
    };
qinsoon's avatar
fix  
qinsoon committed
58

qinsoon's avatar
qinsoon committed
59
    // funcref
qinsoon's avatar
qinsoon committed
60
    (($vm: expr) $name: ident = mu_funcref($sig: ident)) => {
61 62 63 64 65 66 67 68 69
        let $name = $vm.declare_type(MuEntityHeader::named($vm.next_id(), Mu(stringify!($name))), MuType_::funcref($sig.clone()));
        $vm.set_name($name.as_entity());
    };

    // ufuncptr
    (($vm: expr) $name: ident = mu_ufuncptr($sig: ident)) => {
        let $name = $vm.declare_type(MuEntityHeader::named($vm.next_id(), Mu(stringify!($name))), MuType_::ufuncptr($sig.clone()));
        $vm.set_name($name.as_entity());
    };
70 71 72 73
}

macro_rules! constdef {
    (($vm: expr) <$ty: ident> $name: ident = $val: expr) => {
74 75
        let $name = $vm.declare_const(MuEntityHeader::named($vm.next_id(), Mu(stringify!($name))), $ty.clone(), $val);
        $vm.set_name($name.as_entity());
76 77 78
    }
}

79 80
macro_rules! globaldef {
    (($vm: expr) <$ty: ident> $name: ident) => {
81 82
        let $name = $vm.declare_global(MuEntityHeader::named($vm.next_id(), Mu(stringify!($name))), $ty.clone());
        $vm.set_name($name.as_entity());
83 84 85
    }
}

86 87
macro_rules! funcsig {
    (($vm: expr) $name: ident = ($($arg_ty: ident),*) -> ($($ret_ty: ident),*)) => {
88 89
        let $name = $vm.declare_func_sig(MuEntityHeader::named($vm.next_id(), Mu(stringify!($name))), vec![$($ret_ty.clone()),*], vec![$($arg_ty.clone()),*]);
        $vm.set_name($name.as_entity());
90 91 92 93 94
    }
}

macro_rules! funcdecl {
    (($vm: expr) <$sig: ident> $name: ident) => {
95 96
        let func = MuFunction::new(MuEntityHeader::named($vm.next_id(), Mu(stringify!($name))), $sig.clone());
        $vm.set_name(func.as_entity());
97 98 99 100 101 102 103
        let $name = func.id();
        $vm.declare_func(func);
    }
}

macro_rules! funcdef {
    (($vm: expr) <$sig: ident> $func: ident VERSION $version: ident) => {
104 105
        let mut $version = MuFunctionVersion::new(MuEntityHeader::named($vm.next_id(), Mu(stringify!($version))), $func, $sig.clone());
        $vm.set_name($version.as_entity());
106 107 108 109 110
    }
}

macro_rules! define_func_ver {
    (($vm: expr) $fv: ident (entry: $entry: ident){$($blk: ident), *}) => {
111 112 113 114 115
        $fv.define(FunctionContent::new($entry.id(), {
            let mut ret = LinkedHashMap::new();
            $ (ret.insert($blk.id(), $blk); )*
            ret
        }));
116 117 118 119 120 121 122

        $vm.define_func_version($fv);
    }
}

macro_rules! block {
    (($vm: expr, $fv: ident) $name: ident) => {
123 124
        let mut $name = Block::new(MuEntityHeader::named($vm.next_id(), Mu(stringify!($name))));
        $vm.set_name($name.as_entity());
125 126 127 128 129 130 131 132 133 134 135
    }
}

macro_rules! define_block {
    (($vm: expr, $fv: ident) $name: ident ($($arg: ident), *) {$($inst: ident), *}) => {
        $name.content = Some(BlockContent{
            args: vec![$($arg.clone_value()), *],
            exn_arg: None,
            body: vec![$($inst), *],
            keepalives: None
        });
136 137 138 139 140 141 142 143 144
    };

    (($vm: expr, $fv: ident) $name: ident ($($arg: ident), *) [$exn_arg: ident] {$($inst: ident), *}) => {
        $name.content = Some(BlockContent{
            args: vec![$($arg.clone_value()), *],
            exn_arg: Some($exn_arg.clone_value()),
            body: vec![$($inst), *],
            keepalives: None
        });
145 146 147 148 149
    }
}

macro_rules! ssa {
    (($vm: expr, $fv: ident) <$ty: ident> $name: ident) => {
150 151
        let $name = $fv.new_ssa(MuEntityHeader::named($vm.next_id(), Mu(stringify!($name))), $ty.clone());
        $vm.set_name($name.as_entity());
152 153 154 155 156 157 158 159 160
    }
}

macro_rules! consta {
    (($vm: expr, $fv: ident) $name: ident = $c: ident) => {
        let $name = $fv.new_constant($c.clone());
    }
}

161 162 163 164 165 166
macro_rules! global {
    (($vm: expr, $fv: ident) $name: ident = $g: ident) => {
        let $name = $fv.new_global($g.clone());
    }
}

167 168 169 170 171 172
macro_rules! inst {
    // NEW
    (($vm: expr, $fv: ident) $name: ident: $value: ident = NEW <$ty: ident>) => {
        let $name = $fv.new_inst(Instruction{
            hdr:    MuEntityHeader::unnamed($vm.next_id()),
            value:  Some(vec![$value.clone_value()]),
173
            ops:    vec![],
174 175 176 177
            v:      Instruction_::New($ty.clone())
        });
    };

178 179 180 181 182
    // NEWHYBRID
    (($vm: expr, $fv: ident) $name: ident: $value: ident = NEWHYBRID <$ty: ident> $len: ident) => {
        let $name = $fv.new_inst(Instruction{
            hdr:    MuEntityHeader::unnamed($vm.next_id()),
            value:  Some(vec![$value.clone_value()]),
183
            ops:    vec![$len.clone()],
184 185 186 187
            v:      Instruction_::NewHybrid($ty.clone(), 0)
        });
    };

188 189 190 191 192
    // GETIREF
    (($vm: expr, $fv: ident) $name: ident: $value: ident = GETIREF $op: ident) => {
        let $name = $fv.new_inst(Instruction{
            hdr:    MuEntityHeader::unnamed($vm.next_id()),
            value:  Some(vec![$value.clone_value()]),
193
            ops:    vec![$op.clone()],
194 195 196 197 198 199 200 201 202
            v:      Instruction_::GetIRef(0)
        });
    };

    // GETFIELDIREF
    (($vm: expr, $fv: ident) $name: ident: $value: ident = GETFIELDIREF $op: ident (is_ptr: $is_ptr: expr, index: $index: expr)) => {
        let $name = $fv.new_inst(Instruction{
            hdr:    MuEntityHeader::unnamed($vm.next_id()),
            value:  Some(vec![$value.clone_value()]),
203
            ops:    vec![$op.clone()],
204 205 206 207 208 209 210 211
            v:      Instruction_::GetFieldIRef {
                        is_ptr: $is_ptr,
                        base: 0,
                        index: $index
            }
        });
    };

212 213 214 215 216
    // GETELEMIREF
    (($vm: expr, $fv: ident) $name: ident: $value: ident = GETELEMIREF $op: ident $index: ident (is_ptr: $is_ptr: expr)) => {
        let $name = $fv.new_inst(Instruction{
            hdr:    MuEntityHeader::unnamed($vm.next_id()),
            value:  Some(vec![$value.clone_value()]),
217
            ops:    vec![$op.clone(), $index.clone()],
218 219 220 221 222 223 224 225
            v:      Instruction_::GetElementIRef {
                        is_ptr: $is_ptr,
                        base: 0,
                        index: 1
            }
        });
    };

qinsoon's avatar
qinsoon committed
226 227 228 229 230
    // GETVARPARTIREF
    (($vm: expr, $fv: ident) $name: ident: $value: ident = GETVARPARTIREF $op: ident (is_ptr: $is_ptr: expr)) => {
        let $name = $fv.new_inst(Instruction{
            hdr:    MuEntityHeader::unnamed($vm.next_id()),
            value:  Some(vec![$value.clone_value()]),
231
            ops:    vec![$op.clone()],
qinsoon's avatar
qinsoon committed
232 233 234 235 236 237 238 239 240 241 242 243
            v:      Instruction_::GetVarPartIRef {
                        is_ptr: $is_ptr,
                        base: 0
            }
        });
    };

    // SHIFTIREF
    (($vm: expr, $fv: ident) $name: ident: $value: ident = SHIFTIREF $op: ident $offset: ident (is_ptr: $is_ptr: expr)) => {
        let $name = $fv.new_inst(Instruction{
            hdr:    MuEntityHeader::unnamed($vm.next_id()),
            value:  Some(vec![$value.clone_value()]),
244
            ops:    vec![$op.clone(), $offset.clone()],
qinsoon's avatar
qinsoon committed
245 246 247 248 249 250 251 252
            v:      Instruction_::ShiftIRef {
                        is_ptr: $is_ptr,
                        base: 0,
                        offset: 1
            }
        });
    };

253 254 255 256 257
    // STORE
    (($vm: expr, $fv: ident) $name: ident: STORE $loc: ident $val: ident (is_ptr: $is_ptr: expr, order: $order: expr)) => {
        let $name = $fv.new_inst(Instruction{
            hdr:    MuEntityHeader::unnamed($vm.next_id()),
            value:  None,
258
            ops:    vec![$loc.clone(), $val.clone()],
259 260 261 262 263 264 265 266 267 268 269 270 271 272
            v:      Instruction_::Store {
                        is_ptr: $is_ptr,
                        order: $order,
                        mem_loc: 0,
                        value: 1
            }
        });
    };

    // LOAD
    (($vm: expr, $fv: ident) $name: ident: $value: ident = LOAD $loc: ident (is_ptr: $is_ptr: expr, order: $order: expr)) => {
        let $name = $fv.new_inst(Instruction{
            hdr:    MuEntityHeader::unnamed($vm.next_id()),
            value:  Some(vec![$value.clone_value()]),
273
            ops:    vec![$loc.clone()],
274 275 276 277 278 279 280 281 282 283 284 285 286
            v:      Instruction_::Load {
                        is_ptr: $is_ptr,
                        order: $order,
                        mem_loc: 0
            }
        });
    };

    // BINOP
    (($vm: expr, $fv: ident) $name: ident: $value: ident = BINOP ($op: expr) $op1: ident $op2: ident) => {
        let $name = $fv.new_inst(Instruction{
            hdr:    MuEntityHeader::unnamed($vm.next_id()),
            value:  Some(vec![$value.clone_value()]),
287
            ops:    vec![$op1.clone(), $op2.clone()],
288 289 290 291
            v:      Instruction_::BinOp($op, 0, 1)
        });
    };

qinsoon's avatar
qinsoon committed
292 293 294 295 296
    // BINOP with status
    (($vm: expr, $fv: ident) $name: ident: $value: ident, $($flag: ident), * = BINOP_STATUS ($op: expr) ($flags: expr) $op1: ident $op2: ident) => {
        let $name = $fv.new_inst(Instruction{
            hdr:    MuEntityHeader::unnamed($vm.next_id()),
            value:  Some(vec![$value.clone_value(), $($flag.clone_value()), *]),
297
            ops:    vec![$op1.clone(), $op2.clone()],
qinsoon's avatar
qinsoon committed
298 299 300 301
            v:      Instruction_::BinOpWithStatus($op, $flags, 0, 1)
        });
    };

qinsoon's avatar
qinsoon committed
302 303 304 305 306
    // CMPOP
    (($vm: expr, $fv: ident) $name: ident: $value: ident = CMPOP ($op: expr) $op1: ident $op2: ident) => {
        let $name = $fv.new_inst(Instruction{
            hdr: MuEntityHeader::unnamed($vm.next_id()),
            value: Some(vec![$value.clone_value()]),
307
            ops: vec![$op1.clone(), $op2.clone()],
qinsoon's avatar
qinsoon committed
308 309 310 311
            v: Instruction_::CmpOp($op, 0, 1)
        });
    };

312 313 314 315 316
    // CONVOP
    (($vm: expr, $fv: ident) $name: ident: $value: ident = CONVOP ($operation: expr) <$ty1: ident $ty2: ident> $operand: ident) => {
        let $name = $fv.new_inst(Instruction{
            hdr: MuEntityHeader::unnamed($vm.next_id()),
            value: Some(vec![$value.clone_value()]),
317
            ops: vec![$operand.clone()],
318 319 320 321 322 323 324 325 326
            v: Instruction_::ConvOp{
                operation: $operation,
                from_ty: $ty1.clone(),
                to_ty: $ty2.clone(),
                operand: 0
            }
        });
    };

qinsoon's avatar
qinsoon committed
327 328 329 330 331
    // SELECT
    (($vm: expr, $fv: ident) $name: ident: $value: ident = SELECT $cond: ident $op_true: ident $op_false:ident) => {
        let $name = $fv.new_inst(Instruction{
            hdr: MuEntityHeader::unnamed($vm.next_id()),
            value: Some(vec![$value.clone_value()]),
332
            ops: vec![$cond.clone(), $op_true.clone(), $op_false.clone()],
qinsoon's avatar
qinsoon committed
333 334 335 336 337 338 339 340
            v: Instruction_::Select{
                cond: 0,
                true_val: 1,
                false_val: 2
            }
        });
    };

341 342 343 344 345
    // BRANCH
    (($vm: expr, $fv: ident) $name: ident: BRANCH $dest: ident ($($arg: ident), *)) => {
        let $name = $fv.new_inst(Instruction{
            hdr:    MuEntityHeader::unnamed($vm.next_id()),
            value:  None,
346
            ops:    vec![$($arg.clone()),*],
347 348 349 350
            v:      Instruction_::Branch1(Destination{
                        target: $dest.id(),
                        args: {
                            let mut i =0;
qinsoon's avatar
qinsoon committed
351
                            vec![$($arg.clone()),*].iter().map(|_| {let ret = DestArg::Normal(i); i+=1; ret}).collect()
352 353 354 355 356
                        }
            })
        });
    };

qinsoon's avatar
qinsoon committed
357 358 359 360 361 362 363 364 365 366 367 368 369
    // BRANCH2
    // list all operands first
    // then use vector expr to list operands for each destination
    // (we cannot have two repetition list of different lengths in a macro)
    (($vm: expr, $fv: ident) $name: ident:
        BRANCH2 ($($op: ident), *)
            IF (OP $cond: expr)
            THEN $true_dest : ident ($true_args: expr) WITH $prob: expr,
            ELSE $false_dest: ident ($false_args: expr)
    ) => {
        let $name = $fv.new_inst(Instruction{
            hdr:    MuEntityHeader::unnamed($vm.next_id()),
            value:  None,
370
            ops:    vec![$($op.clone()),*],
qinsoon's avatar
qinsoon committed
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
            v:      {
                let true_args = {
                    $true_args.iter().map(|x| DestArg::Normal(*x)).collect()
                };

                let false_args = {
                    $false_args.iter().map(|x| DestArg::Normal(*x)).collect()
                };

                Instruction_::Branch2{
                    cond: $cond,
                    true_dest: Destination {
                        target: $true_dest.id(),
                        args: true_args
                    },
                    false_dest: Destination {
                        target: $false_dest.id(),
                        args: false_args
                    },
                    true_prob: $prob
                }
            }
        });
    };

396
    // EXPRCALL
397
    (($vm: expr, $fv: ident) $name: ident: $res: ident = EXPRCALL ($cc: expr, is_abort: $is_abort: expr) $func: ident ($($val: ident), *)) => {
398
        let ops = vec![$func.clone(), $($val.clone()), *];
qinsoon's avatar
qinsoon committed
399 400 401 402
        let ops_len = ops.len();
        let $name = $fv.new_inst(Instruction{
            hdr:    MuEntityHeader::unnamed($vm.next_id()),
            value:  Some(vec![$res.clone_value()]),
403
            ops:    ops,
qinsoon's avatar
qinsoon committed
404 405 406 407 408 409 410 411 412 413
            v:      Instruction_::ExprCall {
                        data: CallData {
                            func: 0,
                            args: (1..ops_len).collect(),
                            convention: $cc
                        },
                        is_abort: $is_abort
                    }
        });
    };
414
    (($vm: expr, $fv: ident) $name: ident: EXPRCALL ($cc: expr, is_abort: $is_abort: expr) $func: ident ($($val: ident), *)) => {
qinsoon's avatar
[wip]  
qinsoon committed
415 416 417 418 419
        let ops = vec![$func.clone(), $($val.clone()), *];
        let ops_len = ops.len();
        let $name = $fv.new_inst(Instruction{
            hdr:    MuEntityHeader::unnamed($vm.next_id()),
            value:  Some(vec![]),
420
            ops:    ops,
qinsoon's avatar
[wip]  
qinsoon committed
421 422 423 424 425 426 427 428 429 430
            v:      Instruction_::ExprCall {
                        data: CallData {
                            func: 0,
                            args: (1..ops_len).collect(),
                            convention: $cc
                        },
                        is_abort: $is_abort
                    }
        });
    };
431 432 433 434 435 436 437 438

    // EXPRCCALL
    (($vm: expr, $fv: ident) $name: ident: $res: ident = EXPRCCALL ($cc: expr, is_abort: $is_abort: expr) $func: ident ($($val: ident), *)) => {
        let ops = vec![$func.clone(), $($val.clone()), *];
        let ops_len = ops.len();
        let $name = $fv.new_inst(Instruction{
            hdr:    MuEntityHeader::unnamed($vm.next_id()),
            value:  Some(vec![$res.clone_value()]),
439
            ops:    ops,
440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455
            v:      Instruction_::ExprCCall {
                        data: CallData {
                            func: 0,
                            args: (1..ops_len).collect(),
                            convention: $cc
                        },
                        is_abort: $is_abort
                    }
        });
    };
    (($vm: expr, $fv: ident) $name: ident: EXPRCCALL ($cc: expr, is_abort: $is_abort: expr) $func: ident ($($val: ident), *)) => {
        let ops = vec![$func.clone(), $($val.clone()), *];
        let ops_len = ops.len();
        let $name = $fv.new_inst(Instruction{
            hdr:    MuEntityHeader::unnamed($vm.next_id()),
            value:  Some(vec![]),
456
            ops:    ops,
457 458 459 460 461 462 463 464 465 466 467
            v:      Instruction_::ExprCCall {
                        data: CallData {
                            func: 0,
                            args: (1..ops_len).collect(),
                            convention: $cc
                        },
                        is_abort: $is_abort
                    }
        });
    };

468
    // CALL (1 return result)
469 470 471 472 473 474 475
    (($vm: expr, $fv: ident) $name: ident:
        $res: ident = CALL ($($op: ident), *) FUNC($func: expr) ($args: expr) $cc: expr,
                      normal: $norm_dest: ident ($norm_args: expr),
                      exc: $exc_dest: ident ($exc_args: expr)) => {
        let $name = $fv.new_inst(Instruction {
            hdr  : MuEntityHeader::unnamed($vm.next_id()),
            value: Some(vec![$res.clone_value()]),
476
            ops  : vec![$($op.clone()),*],
477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495
            v    : Instruction_::Call {
                data: CallData {
                    func: $func,
                    args: $args,
                    convention: $cc
                },
                resume: ResumptionData {
                    normal_dest: Destination {
                        target: $norm_dest.id(),
                        args  : $norm_args
                    },
                    exn_dest: Destination {
                        target: $exc_dest.id(),
                        args  : $exc_args
                    }
                }
            }
        });
    };
496 497 498 499 500 501 502 503
    // CALL (no return value)
    (($vm: expr, $fv: ident) $name: ident:
        CALL ($($op: ident), *) FUNC($func: expr) ($args: expr) $cc: expr,
                      normal: $norm_dest: ident ($norm_args: expr),
                      exc: $exc_dest: ident ($exc_args: expr)) => {
        let $name = $fv.new_inst(Instruction {
            hdr  : MuEntityHeader::unnamed($vm.next_id()),
            value: None,
504
            ops  : vec![$($op.clone()),*],
505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524
            v    : Instruction_::Call {
                data: CallData {
                    func: $func,
                    args: $args,
                    convention: $cc
                },
                resume: ResumptionData {
                    normal_dest: Destination {
                        target: $norm_dest.id(),
                        args  : $norm_args
                    },
                    exn_dest: Destination {
                        target: $exc_dest.id(),
                        args  : $exc_args
                    }
                }
            }
        });
    };

qinsoon's avatar
qinsoon committed
525

526
    // RET
527
    (($vm: expr, $fv: ident) $name: ident: RET ($($val: ident), +)) => {
528 529 530
        let $name = $fv.new_inst(Instruction{
            hdr:    MuEntityHeader::unnamed($vm.next_id()),
            value:  None,
531
            ops:    vec![$($val.clone()), *],
532 533
            v:      Instruction_::Return({
                        let mut i = 0;
qinsoon's avatar
qinsoon committed
534
                        vec![$($val.clone()), *].iter().map(|_| {let ret = i; i+= 1; ret}).collect()
535 536 537
                    })
        });
    };
538 539 540 541 542
    // RET (no value)
    (($vm: expr, $fv: ident) $name: ident: RET) => {
        let $name = $fv.new_inst(Instruction{
            hdr:    MuEntityHeader::unnamed($vm.next_id()),
            value:  None,
543
            ops:    vec![],
544 545 546
            v:      Instruction_::Return(vec![])
        });
    };
547 548 549 550 551 552

    // THREADEXIT
    (($vm: expr, $fv: ident) $name: ident: THREADEXIT) => {
        let $name = $fv.new_inst(Instruction{
            hdr: MuEntityHeader::unnamed($vm.next_id()),
            value: None,
553
            ops: vec![],
554 555 556 557
            v: Instruction_::ThreadExit
        });
    };

558 559 560 561 562
    // THROW
    (($vm: expr, $fv: ident) $name: ident: THROW $op: ident) => {
        let $name = $fv.new_inst(Instruction{
            hdr: MuEntityHeader::unnamed($vm.next_id()),
            value: None,
563
            ops: vec![$op.clone()],
564 565 566 567
            v: Instruction_::Throw(0)
        });
    };

568 569 570 571 572
    // PRINTHEX
    (($vm: expr, $fv: ident) $name: ident: PRINTHEX $val: ident) => {
        let $name = $fv.new_inst(Instruction{
            hdr: MuEntityHeader::unnamed($vm.next_id()),
            value: None,
573
            ops: vec![$val.clone()],
574 575 576
            v: Instruction_::PrintHex(0)
        });
    }
577
}