test_mem_inst.rs 43.1 KB
Newer Older
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Copyright 2017 The Australian National University
// 
// 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
// 
//     http://www.apache.org/licenses/LICENSE-2.0
// 
// 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.

15
16
extern crate libloading;

17
18
19
20
21
22
use mu::ast::types::*;
use mu::ast::ir::*;
use mu::ast::inst::*;
use mu::ast::op::*;
use mu::vm::*;
use mu::compiler::*;
23
use mu::utils::LinkedHashMap;
24
use mu::utils::mem::memsec;
25
26

use std::sync::Arc;
qinsoon's avatar
qinsoon committed
27
28
use mu::linkutils::aot;
use mu::linkutils;
29
30
31

use test_compiler::test_call::gen_ccall_exit;

32
33
#[test]
fn test_store_seqcst() {
qinsoon's avatar
qinsoon committed
34
    let lib = linkutils::aot::compile_fnc("store_seqcst", &store_seqcst);
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84

    unsafe {
        let ptr : *mut u64 = match memsec::malloc(8) {
            Some(ptr) => ptr,
            None => panic!("failed to allocate memory for test")
        };

        let store_seqcst : libloading::Symbol<unsafe extern fn(*mut u64, u64)> = lib.get(b"store_seqcst").unwrap();

        store_seqcst(ptr, 42);
        let load_val = *ptr;
        println!("result = {}", load_val);
        assert!(load_val == 42);
    }
}

fn store_seqcst() -> VM {
    let vm = VM::new();

    typedef!    ((vm) int64      = mu_int(64));
    typedef!    ((vm) iref_int64 = mu_iref(int64));

    funcsig!    ((vm) sig = (iref_int64, int64) -> ());
    funcdecl!   ((vm) <sig> store_seqcst);
    funcdef!    ((vm) <sig> store_seqcst VERSION store_seqcst_v1);

    block!      ((vm, store_seqcst_v1) blk_entry);
    ssa!        ((vm, store_seqcst_v1) <iref_int64> loc);
    ssa!        ((vm, store_seqcst_v1) <int64> val);

    inst!       ((vm, store_seqcst_v1) blk_entry_store:
        STORE loc val (is_ptr: false, order: MemoryOrder::SeqCst)
    );

    inst!       ((vm, store_seqcst_v1) blk_entry_ret:
        RET
    );

    define_block!((vm, store_seqcst_v1) blk_entry(loc, val) {
        blk_entry_store,
        blk_entry_ret
    });

    define_func_ver!((vm) store_seqcst_v1 (entry: blk_entry) {
        blk_entry
    });

    vm
}

85
86
87
88
#[repr(C)]
struct Foo (i8, i8, i8);

#[test]
qinsoon's avatar
qinsoon committed
89
#[allow(unused_variables)]
90
fn test_write_int8_val() {
qinsoon's avatar
qinsoon committed
91
    let lib = linkutils::aot::compile_fnc("write_int8", &write_int8);
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

    unsafe {
        let ptr : *mut Foo = Box::into_raw(Box::new(Foo(1, 2, 3)));
        let a = (*ptr).0;
        let b = (*ptr).1;
        let c = (*ptr).2;
        println!("foo.0 = {}", (*ptr).0);
        println!("foo.1 = {}", (*ptr).1);
        println!("foo.2 = {}", (*ptr).2);

        let write_int8 : libloading::Symbol<unsafe extern fn(*mut Foo, i8)> = lib.get(b"write_int8").unwrap();

        write_int8(ptr, 42);

        println!("foo.0 = {}", (*ptr).0);
        println!("foo.1 = {}", (*ptr).1);
        println!("foo.2 = {}", (*ptr).2);

        assert_eq!((*ptr).0, a);
        assert_eq!((*ptr).1, 42);
        assert_eq!((*ptr).2, c);
    }
}

fn write_int8() -> VM {
    let vm = VM::new();

    typedef!    ((vm) int8 = mu_int(8));
    typedef!    ((vm) foo  = mu_struct(int8, int8, int8));
    typedef!    ((vm) ref_foo   = mu_ref(foo));
    typedef!    ((vm) iref_foo  = mu_iref(foo));
    typedef!    ((vm) iref_int8 = mu_iref(int8));

    funcsig!    ((vm) write_int8_sig = (ref_foo, int8) -> ());
    funcdecl!   ((vm) <write_int8_sig> write_int8);
    funcdef!    ((vm) <write_int8_sig> write_int8 VERSION write_int8_v1);

    block!      ((vm, write_int8_v1) blk_entry);
    ssa!        ((vm, write_int8_v1) <ref_foo> refx);
    ssa!        ((vm, write_int8_v1) <int8> val);

    ssa!        ((vm, write_int8_v1) <iref_foo> irefx);
    inst!       ((vm, write_int8_v1) blk_entry_getiref:
        irefx = GETIREF refx
    );

    ssa!        ((vm, write_int8_v1) <iref_int8> iref_field1);
    inst!       ((vm, write_int8_v1) blk_entry_getfieldiref:
        iref_field1 = GETFIELDIREF irefx (is_ptr: false, index: 1)
    );

    inst!       ((vm, write_int8_v1) blk_entry_write:
        STORE iref_field1 val (is_ptr: false, order: MemoryOrder::Relaxed)
    );

    inst!       ((vm, write_int8_v1) blk_entry_ret:
        RET
    );

    define_block!((vm, write_int8_v1) blk_entry(refx, val) {
        blk_entry_getiref, blk_entry_getfieldiref, blk_entry_write, blk_entry_ret
    });

    define_func_ver!((vm) write_int8_v1 (entry: blk_entry) {blk_entry});

    vm
}

160
#[allow(unused_variables)]
161
162
#[test]
fn test_write_int8_const() {
qinsoon's avatar
qinsoon committed
163
    let lib = linkutils::aot::compile_fnc("write_int8_const", &write_int8_const);
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233

    unsafe {
        let ptr : *mut Foo = Box::into_raw(Box::new(Foo(1, 2, 3)));
        let a = (*ptr).0;
        let b = (*ptr).1;
        let c = (*ptr).2;
        println!("foo.0 = {}", (*ptr).0);
        println!("foo.1 = {}", (*ptr).1);
        println!("foo.2 = {}", (*ptr).2);

        let write_int8 : libloading::Symbol<unsafe extern fn(*mut Foo)> = lib.get(b"write_int8_const").unwrap();

        write_int8(ptr);

        println!("foo.0 = {}", (*ptr).0);
        println!("foo.1 = {}", (*ptr).1);
        println!("foo.2 = {}", (*ptr).2);

        assert_eq!((*ptr).0, a);
        assert_eq!((*ptr).1, 42);
        assert_eq!((*ptr).2, c);
    }
}

fn write_int8_const() -> VM {
    let vm = VM::new();

    typedef!    ((vm) int8 = mu_int(8));
    typedef!    ((vm) foo  = mu_struct(int8, int8, int8));
    typedef!    ((vm) ref_foo   = mu_ref(foo));
    typedef!    ((vm) iref_foo  = mu_iref(foo));
    typedef!    ((vm) iref_int8 = mu_iref(int8));

    constdef!   ((vm) <int8> int8_42 = Constant::Int(42));

    funcsig!    ((vm) write_int8_const_sig = (ref_foo) -> ());
    funcdecl!   ((vm) <write_int8_const_sig> write_int8_const);
    funcdef!    ((vm) <write_int8_const_sig> write_int8_const VERSION write_int8_const_v1);

    block!      ((vm, write_int8_const_v1) blk_entry);
    ssa!        ((vm, write_int8_const_v1) <ref_foo> refx);

    ssa!        ((vm, write_int8_const_v1) <iref_foo> irefx);
    inst!       ((vm, write_int8_const_v1) blk_entry_getiref:
        irefx = GETIREF refx
    );

    ssa!        ((vm, write_int8_const_v1) <iref_int8> iref_field1);
    inst!       ((vm, write_int8_const_v1) blk_entry_getfieldiref:
        iref_field1 = GETFIELDIREF irefx (is_ptr: false, index: 1)
    );

    consta!     ((vm, write_int8_const_v1) int8_42_local = int8_42);
    inst!       ((vm, write_int8_const_v1) blk_entry_write:
        STORE iref_field1 int8_42_local (is_ptr: false, order: MemoryOrder::Relaxed)
    );

    inst!       ((vm, write_int8_const_v1) blk_entry_ret:
        RET
    );

    define_block!((vm, write_int8_const_v1) blk_entry(refx) {
        blk_entry_getiref, blk_entry_getfieldiref, blk_entry_write, blk_entry_ret
    });

    define_func_ver!((vm) write_int8_const_v1 (entry: blk_entry) {blk_entry});

    vm
}

234
235
#[test]
fn test_get_field_iref1() {
qinsoon's avatar
qinsoon committed
236
    let lib = linkutils::aot::compile_fnc("get_field_iref1", &get_field_iref1);
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292

    unsafe {
        let get_field_iref1 : libloading::Symbol<unsafe extern fn(u64) -> u64> = lib.get(b"get_field_iref1").unwrap();

        let addr = 0x10000000;
        let res = get_field_iref1(addr);
        println!("get_field_iref1({}) = {}", addr, res);

        assert!(addr + 8 == res);
    }
}

fn get_field_iref1() -> VM {
    let vm = VM::new();

    typedef!    ((vm) int64         = mu_int(64));
    typedef!    ((vm) ref_int64     = mu_ref(int64));
    typedef!    ((vm) iref_int64    = mu_iref(int64));
    typedef!    ((vm) mystruct      = mu_struct(int64, int64, ref_int64));
    typedef!    ((vm) ref_mystruct  = mu_ref(mystruct));
    typedef!    ((vm) iref_mystruct = mu_iref(mystruct));

    funcsig!    ((vm) sig = (ref_mystruct) -> (iref_int64));
    funcdecl!   ((vm) <sig> get_field_iref1);

    funcdef!    ((vm) <sig> get_field_iref1 VERSION get_field_iref1_v1);

    block!      ((vm, get_field_iref1_v1) blk_entry);
    ssa!        ((vm, get_field_iref1_v1) <ref_mystruct> x);

    ssa!        ((vm, get_field_iref1_v1) <iref_mystruct> x_);
    inst!       ((vm, get_field_iref1_v1) blk_entry_get_iref:
        x_ = GETIREF x
    );

    ssa!        ((vm, get_field_iref1_v1) <iref_int64> ret);
    inst!       ((vm, get_field_iref1_v1) blk_entry_get_field_iref1:
        ret = GETFIELDIREF x_ (is_ptr: false, index: 1)
    );

    inst!       ((vm, get_field_iref1_v1) blk_entry_ret:
        RET (ret)
    );


    define_block!   ((vm, get_field_iref1_v1) blk_entry(x) {
        blk_entry_get_iref, blk_entry_get_field_iref1, blk_entry_ret
    });

    define_func_ver!((vm) get_field_iref1_v1 (entry: blk_entry) {blk_entry});

    vm
}

#[test]
fn test_get_iref() {
qinsoon's avatar
qinsoon committed
293
    let lib = linkutils::aot::compile_fnc("get_iref", &get_iref);
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338

    unsafe {
        let get_iref : libloading::Symbol<unsafe extern fn(u64) -> u64> = lib.get(b"get_iref").unwrap();

        let addr = 0x10000000;
        let res = get_iref(addr);
        println!("get_iref({}) = {}", addr, res);

        assert!(addr == res);
    }
}

fn get_iref() -> VM {
    let vm = VM::new();

    typedef!    ((vm) int64      = mu_int(64));
    typedef!    ((vm) ref_int64  = mu_ref(int64));
    typedef!    ((vm) iref_int64 = mu_iref(int64));

    funcsig!    ((vm) sig = (ref_int64) -> (iref_int64));
    funcdecl!   ((vm) <sig> get_iref);

    funcdef!    ((vm) <sig> get_iref VERSION get_iref_v1);

    block!      ((vm, get_iref_v1) blk_entry);
    ssa!        ((vm, get_iref_v1) <ref_int64> x);

    ssa!        ((vm, get_iref_v1) <iref_int64> ret);
    inst!       ((vm, get_iref_v1) blk_entry_get_iref:
        ret = GETIREF x
    );

    inst!       ((vm, get_iref_v1) blk_entry_ret:
        RET (ret)
    );

    define_block!   ((vm, get_iref_v1) blk_entry(x) {
        blk_entry_get_iref, blk_entry_ret
    });

    define_func_ver!((vm) get_iref_v1 (entry: blk_entry) {blk_entry});

    vm
}

339
340
341
342
#[test]
fn test_struct() {
    VM::start_logging_trace();

qinsoon's avatar
qinsoon committed
343
    let vm = Arc::new(struct_insts_macro());
344

qinsoon's avatar
qinsoon committed
345
    let compiler = Compiler::new(CompilerPolicy::default(), &vm);
346
347
348
349
350
351
352
353
354
355
356

    let func_id = vm.id_of("struct_insts");
    {
        let funcs = vm.funcs().read().unwrap();
        let func = funcs.get(&func_id).unwrap().read().unwrap();
        let func_vers = vm.func_vers().read().unwrap();
        let mut func_ver = func_vers.get(&func.cur_ver.unwrap()).unwrap().write().unwrap();

        compiler.compile(&mut func_ver);
    }

qinsoon's avatar
qinsoon committed
357
    vm.set_primordial_thread(func_id, true, vec![]);
358
359
    backend::emit_context(&vm);

qinsoon's avatar
qinsoon committed
360
    let executable = aot::link_primordial(vec!["struct_insts".to_string()], "struct_insts_test", &vm);
qinsoon's avatar
qinsoon committed
361
    let output = linkutils::exec_path_nocheck(executable);
362
363
364
365
366
367
368
369

    assert!(output.status.code().is_some());

    let ret_code = output.status.code().unwrap();
    println!("return code: {}", ret_code);
    assert!(ret_code == 1);
}

qinsoon's avatar
qinsoon committed
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
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
// this IR construction function is a replicate of struct_insts() with macros
pub fn struct_insts_macro() -> VM {
    let vm = VM::new();

    typedef! ((vm) int64        = mu_int(64));
    typedef! ((vm) struct_point = mu_struct(int64, int64));
    typedef! ((vm) ref_point    = mu_ref(struct_point));
    typedef! ((vm) iref_point   = mu_iref(struct_point));
    typedef! ((vm) iref_int64   = mu_iref(int64));

    constdef!((vm) <int64> int64_0 = Constant::Int(0));
    constdef!((vm) <int64> int64_1 = Constant::Int(1));

    funcsig! ((vm) noparam_noret_sig = () -> ());
    funcdecl!((vm) <noparam_noret_sig> struct_insts);

    funcdef! ((vm) <noparam_noret_sig> struct_insts VERSION struct_insts_v1);

    // blk entry
    block!  ((vm, struct_insts_v1) blk_entry);

    ssa!    ((vm, struct_insts_v1) <ref_point> blk_entry_a);
    inst!   ((vm, struct_insts_v1) blk_entry_inst0:
                blk_entry_a = NEW <struct_point>
    );

    ssa!    ((vm, struct_insts_v1) <iref_point> blk_entry_iref_a);
    inst!   ((vm, struct_insts_v1) blk_entry_inst1:
                blk_entry_iref_a = GETIREF blk_entry_a
    );

    ssa!    ((vm, struct_insts_v1) <iref_int64> blk_entry_iref_x);
    inst!   ((vm, struct_insts_v1) blk_entry_inst2:
                blk_entry_iref_x = GETFIELDIREF blk_entry_iref_a (is_ptr: false, index: 0)
    );

    consta! ((vm, struct_insts_v1) int64_1_local = int64_1);
    inst!   ((vm, struct_insts_v1) blk_entry_inst3:
                STORE blk_entry_iref_x int64_1_local (is_ptr: false, order: MemoryOrder::Relaxed)
    );

    block!  ((vm, struct_insts_v1) blk_check);
    inst!   ((vm, struct_insts_v1) blk_entry_branch:
                BRANCH blk_check (blk_entry_a)
    );

    define_block! ((vm, struct_insts_v1) blk_entry() {
        blk_entry_inst0, blk_entry_inst1, blk_entry_inst2, blk_entry_inst3, blk_entry_branch
    });

    // blk check
    ssa!    ((vm, struct_insts_v1) <ref_point> blk_check_a);

    ssa!    ((vm, struct_insts_v1) <iref_point> blk_check_iref_a);
    inst!   ((vm, struct_insts_v1) blk_check_inst0:
                blk_check_iref_a = GETIREF blk_check_a
    );

    ssa!    ((vm, struct_insts_v1) <iref_int64> blk_check_iref_x);
    inst!   ((vm, struct_insts_v1) blk_check_inst1:
                blk_check_iref_x = GETFIELDIREF blk_check_iref_a (is_ptr: false, index: 0)
    );

    ssa!    ((vm, struct_insts_v1) <int64> blk_check_x);
    inst!   ((vm, struct_insts_v1) blk_check_inst2:
                blk_check_x = LOAD blk_check_iref_x (is_ptr: false, order: MemoryOrder::Relaxed)
    );

    ssa!    ((vm, struct_insts_v1) <iref_int64> blk_check_iref_y);
    inst!   ((vm, struct_insts_v1) blk_check_inst3:
                blk_check_iref_y = GETFIELDIREF blk_check_iref_a (is_ptr: false, index: 1)
    );

    ssa!    ((vm, struct_insts_v1) <int64> blk_check_y);
    inst!   ((vm, struct_insts_v1) blk_check_inst4:
                blk_check_y = LOAD blk_check_iref_y (is_ptr: false, order: MemoryOrder::Relaxed)
    );

    ssa!    ((vm, struct_insts_v1) <int64> blk_check_res);
    inst!   ((vm, struct_insts_v1) blk_check_inst5:
                blk_check_res = BINOP (BinOp::Add) blk_check_x blk_check_y
    );

    let blk_check_ccall = gen_ccall_exit(blk_check_res.clone(), &mut struct_insts_v1, &vm);

    inst!   ((vm, struct_insts_v1) blk_check_ret:
456
                RET
qinsoon's avatar
qinsoon committed
457
458
459
460
461
462
463
464
465
466
467
468
    );

    define_block! ((vm, struct_insts_v1) blk_check(blk_check_a) {
        blk_check_inst0, blk_check_inst1, blk_check_inst2, blk_check_inst3, blk_check_inst4, blk_check_inst5, blk_check_ccall, blk_check_ret
    });

    define_func_ver! ((vm) struct_insts_v1 (entry: blk_entry) {blk_entry, blk_check});

    vm
}

#[allow(dead_code)]
469
470
471
pub fn struct_insts() -> VM {
    let vm = VM::new();

472
473
474
475
476
    typedef!        ((vm) int64 = mu_int(64));
    typedef!        ((vm) point = mu_struct(int64, int64));
    typedef!        ((vm) ref_point  = mu_ref(point));
    typedef!        ((vm) iref_point = mu_iref(point));
    typedef!        ((vm) iref_int64 = mu_iref(int64));
477

478
479
    constdef!       ((vm) <int64> int64_0 = Constant::Int(0));
    constdef!       ((vm) <int64> int64_1 = Constant::Int(1));
480

481
482
483
484
    // .funcsig @noparam_noret_sig = () -> ()
    funcsig!        ((vm) noparam_noret_sig = () -> ());
    funcdecl!       ((vm) <noparam_noret_sig> struct_insts);
    funcdef!        ((vm) <noparam_noret_sig> struct_insts VERSION struct_insts_v1);
485
486

    // %entry():
487
    block!          ((vm, struct_insts_v1) blk_entry);
488
489

    // %a = NEW <@point>
490
491
492
493
    ssa!            ((vm, struct_insts_v1) <ref_point> a);
    inst!           ((vm, struct_insts_v1) blk_entry_new:
        a = NEW <point>
    );
494
495

    // %iref_a = GETIREF <@int64> %a
496
497
498
499
    ssa!            ((vm, struct_insts_v1) <iref_point> iref_a);
    inst!           ((vm, struct_insts_v1) blk_entry_getiref:
        iref_a = GETIREF a
    );
500
501

    // %iref_x = GETFIELDIREF <@point 0> %iref_a
502
503
504
505
    ssa!            ((vm, struct_insts_v1) <iref_int64> iref_x);
    inst!           ((vm, struct_insts_v1) blk_entry_getfield:
        iref_x = GETFIELDIREF iref_a (is_ptr: false, index: 0)
    );
506
507

    // STORE <@int64> %iref_x @int64_1
508
509
510
511
    consta!         ((vm, struct_insts_v1) int64_1_local = int64_1);
    inst!           ((vm, struct_insts_v1) blk_entry_store:
        STORE iref_x int64_1_local (is_ptr: false, order: MemoryOrder::Relaxed)
    );
512
513

    // BRANCH %check(%a)
514
515
516
517
    block!          ((vm, struct_insts_v1) blk_check);
    inst!           ((vm, struct_insts_v1) blk_entry_branch:
        BRANCH blk_check (a)
    );
518

519
520
521
522
523
524
    define_block!   ((vm, struct_insts_v1) blk_entry() {
        blk_entry_new,
        blk_entry_getiref,
        blk_entry_getfield,
        blk_entry_store,
        blk_entry_branch
525
526
527
    });

    // %check(%a):
528
    ssa!            ((vm, struct_insts_v1) <ref_point> blk_check_a);
529
530

    // %blk_check_iref_a = GETIREF <@point> a
531
532
533
534
    ssa!            ((vm, struct_insts_v1) <iref_point> blk_check_iref_a);
    inst!           ((vm, struct_insts_v1) blk_check_getiref:
        blk_check_iref_a = GETIREF blk_check_a
    );
535
536

    // %blk_check_iref_x = GETFIELDIREF <@point 0> %blk_check_iref_a
537
538
539
540
    ssa!            ((vm, struct_insts_v1) <iref_int64> blk_check_iref_x);
    inst!           ((vm, struct_insts_v1) blk_check_getfield:
        blk_check_iref_x = GETFIELDIREF blk_check_iref_a (is_ptr: false, index: 0)
    );
541
542

    // %x = LOAD <@int64> %blk_check_iref_x
543
544
545
546
    ssa!            ((vm, struct_insts_v1) <int64> blk_check_x);
    inst!           ((vm, struct_insts_v1) blk_check_load:
        blk_check_x = LOAD blk_check_iref_x (is_ptr: false, order: MemoryOrder::Relaxed)
    );
547
548

    // %blk_check_iref_y = GETFIELDIREF <@point 1> %blk_check_iref_a
549
550
551
552
    ssa!            ((vm, struct_insts_v1) <iref_int64> blk_check_iref_y);
    inst!           ((vm, struct_insts_v1) blk_check_getfield2:
        blk_check_iref_y = GETFIELDIREF blk_check_iref_a (is_ptr: false, index: 1)
    );
553
554

    // %y = LOAD <@int64> %blk_check_iref_y
555
556
557
558
    ssa!            ((vm, struct_insts_v1) <int64> blk_check_y);
    inst!           ((vm, struct_insts_v1) blk_check_load2:
        blk_check_y = LOAD blk_check_iref_y (is_ptr: false, order: MemoryOrder::Relaxed)
    );
559
560

    // %res = ADD <@int64> %x %y
561
562
563
564
    ssa!            ((vm, struct_insts_v1) <int64> res);
    inst!           ((vm, struct_insts_v1) blk_check_add:
        res = BINOP (BinOp::Add) blk_check_x blk_check_y
    );
565
566

    // CCALL exit(%res)
567
    let blk_check_ccall = gen_ccall_exit(res.clone(), &mut struct_insts_v1, &vm);
568
569

    // RET <@int64> 0
570
571
572
573
    consta!         ((vm, struct_insts_v1) int64_0_local = int64_0);
    inst!           ((vm, struct_insts_v1) blk_check_ret:
        RET (int64_0_local)
    );
574

575
576
577
578
579
580
581
582
583
    define_block!   ((vm, struct_insts_v1) blk_check(blk_check_a) {
        blk_check_getiref,
        blk_check_getfield,
        blk_check_load,
        blk_check_getfield2,
        blk_check_load2,
        blk_check_add,
        blk_check_ccall,
        blk_check_ret
584
585
    });

586
587
588
589
    define_func_ver!((vm) struct_insts_v1(entry: blk_entry) {
        blk_entry,
        blk_check
    });
590

qinsoon's avatar
qinsoon committed
591
592
593
594
595
596
597
598
599
    vm
}

#[test]
fn test_hybrid_fix_part() {
    VM::start_logging_trace();

    let vm = Arc::new(hybrid_fix_part_insts());

qinsoon's avatar
qinsoon committed
600
    let compiler = Compiler::new(CompilerPolicy::default(), &vm);
qinsoon's avatar
qinsoon committed
601
602
603
604
605
606
607
608
609
610
611

    let func_id = vm.id_of("hybrid_fix_part_insts");
    {
        let funcs = vm.funcs().read().unwrap();
        let func = funcs.get(&func_id).unwrap().read().unwrap();
        let func_vers = vm.func_vers().read().unwrap();
        let mut func_ver = func_vers.get(&func.cur_ver.unwrap()).unwrap().write().unwrap();

        compiler.compile(&mut func_ver);
    }

qinsoon's avatar
qinsoon committed
612
    vm.set_primordial_thread(func_id, true, vec![]);
qinsoon's avatar
qinsoon committed
613
614
    backend::emit_context(&vm);

qinsoon's avatar
qinsoon committed
615
    let executable = aot::link_primordial(vec!["hybrid_fix_part_insts".to_string()], "hybrid_fix_part_insts_test", &vm);
qinsoon's avatar
qinsoon committed
616
    let output = linkutils::exec_path_nocheck(executable);
qinsoon's avatar
qinsoon committed
617
618
619
620
621
622
623
624
625
626
627

    assert!(output.status.code().is_some());

    let ret_code = output.status.code().unwrap();
    println!("return code: {}", ret_code);
    assert!(ret_code == 1);
}

pub fn hybrid_fix_part_insts() -> VM {
    let vm = VM::new();

628
629
630
631
632
    typedef!        ((vm) int64 = mu_int(64));
    typedef!        ((vm) my_hybrid   = mu_hybrid(int64, int64)(int64));
    typedef!        ((vm) ref_hybrid  = mu_ref(my_hybrid));
    typedef!        ((vm) iref_hybrid = mu_iref(my_hybrid));
    typedef!        ((vm) iref_int64  = mu_iref(int64));
qinsoon's avatar
qinsoon committed
633

634
635
636
    constdef!       ((vm) <int64> int64_0  = Constant::Int(0));
    constdef!       ((vm) <int64> int64_1  = Constant::Int(1));
    constdef!       ((vm) <int64> int64_10 = Constant::Int(10));
qinsoon's avatar
qinsoon committed
637

638
639
640
    funcsig!        ((vm) noparam_noret_sig = () -> ());
    funcdecl!       ((vm) <noparam_noret_sig> hybrid_fix_part_insts);
    funcdef!        ((vm) <noparam_noret_sig> hybrid_fix_part_insts VERSION hybrid_fix_part_insts_v1);
qinsoon's avatar
qinsoon committed
641
642

    // %entry():
643
    block!          ((vm, hybrid_fix_part_insts_v1) blk_entry);
qinsoon's avatar
qinsoon committed
644
645

    // %a = NEWHYBRID <@my_hybrid @int64> @int64_10
646
647
648
649
650
    ssa!            ((vm, hybrid_fix_part_insts_v1) <ref_hybrid> a);
    consta!         ((vm, hybrid_fix_part_insts_v1) int64_10_local = int64_10);
    inst!           ((vm, hybrid_fix_part_insts_v1) blk_entry_newhybrid:
        a = NEWHYBRID <my_hybrid> int64_10_local
    );
qinsoon's avatar
qinsoon committed
651
652

    // %iref_a = GETIREF <@int64> %a
653
654
655
656
    ssa!            ((vm, hybrid_fix_part_insts_v1) <iref_hybrid> iref_a);
    inst!           ((vm, hybrid_fix_part_insts_v1) blk_entry_getiref:
        iref_a = GETIREF a
    );
qinsoon's avatar
qinsoon committed
657
658

    // %iref_x = GETFIELDIREF <@my_hybrid 0> %iref_a
659
660
661
662
    ssa!            ((vm, hybrid_fix_part_insts_v1) <iref_int64> iref_x);
    inst!           ((vm, hybrid_fix_part_insts_v1) blk_entry_getfield:
        iref_x = GETFIELDIREF iref_a (is_ptr: false, index: 0)
    );
qinsoon's avatar
qinsoon committed
663
664

    // STORE <@int64> %iref_x @int64_1
665
666
667
668
    consta!         ((vm, hybrid_fix_part_insts_v1) int64_1_local = int64_1);
    inst!           ((vm, hybrid_fix_part_insts_v1) blk_entry_store:
        STORE iref_x int64_1_local (is_ptr: false, order: MemoryOrder::Relaxed)
    );
qinsoon's avatar
qinsoon committed
669
670

    // BRANCH %check(%a)
671
672
673
674
    block!          ((vm, hybrid_fix_part_insts_v1) blk_check);
    inst!           ((vm, hybrid_fix_part_insts_v1) blk_entry_branch:
        BRANCH blk_check (a)
    );
qinsoon's avatar
qinsoon committed
675

676
677
678
679
680
681
    define_block!   ((vm, hybrid_fix_part_insts_v1) blk_entry() {
        blk_entry_newhybrid,
        blk_entry_getiref,
        blk_entry_getfield,
        blk_entry_store,
        blk_entry_branch
qinsoon's avatar
qinsoon committed
682
683
684
    });

    // %check(%a):
685
    ssa!            ((vm, hybrid_fix_part_insts_v1) <ref_hybrid> blk_check_a);
qinsoon's avatar
qinsoon committed
686
687

    // %blk_check_iref_a = GETIREF <@my_hybrid> a
688
689
690
691
    ssa!            ((vm, hybrid_fix_part_insts_v1) <iref_hybrid> blk_check_iref_a);
    inst!           ((vm, hybrid_fix_part_insts_v1) blk_check_getiref:
        blk_check_iref_a = GETIREF blk_check_a
    );
qinsoon's avatar
qinsoon committed
692
693

    // %blk_check_iref_x = GETFIELDIREF <@my_hybrid 0> %blk_check_iref_a
694
695
696
697
    ssa!            ((vm, hybrid_fix_part_insts_v1) <iref_int64> blk_check_iref_x);
    inst!           ((vm, hybrid_fix_part_insts_v1) blk_check_getfield:
        blk_check_iref_x = GETFIELDIREF blk_check_iref_a (is_ptr: false, index: 0)
    );
qinsoon's avatar
qinsoon committed
698
699

    // %x = LOAD <@int64> %blk_check_iref_x
700
701
702
703
    ssa!            ((vm, hybrid_fix_part_insts_v1) <int64> blk_check_x);
    inst!           ((vm, hybrid_fix_part_insts_v1) blk_check_load:
        blk_check_x = LOAD blk_check_iref_x (is_ptr: false, order: MemoryOrder::Relaxed)
    );
qinsoon's avatar
qinsoon committed
704
705

    // %blk_check_iref_y = GETFIELDIREF <@my_hybrid 1> %blk_check_iref_a
706
707
708
709
    ssa!            ((vm, hybrid_fix_part_insts_v1) <iref_int64> blk_check_iref_y);
    inst!           ((vm, hybrid_fix_part_insts_v1) blk_check_getfield2:
        blk_check_iref_y = GETFIELDIREF blk_check_iref_a (is_ptr: false, index: 1)
    );
qinsoon's avatar
qinsoon committed
710
711

    // %y = LOAD <@int64> %blk_check_iref_y
712
713
714
715
    ssa!            ((vm, hybrid_fix_part_insts_v1) <int64> blk_check_y);
    inst!           ((vm, hybrid_fix_part_insts_v1) blk_check_load2:
        blk_check_y = LOAD blk_check_iref_y (is_ptr: false, order: MemoryOrder::Relaxed)
    );
qinsoon's avatar
qinsoon committed
716
717

    // %res = ADD <@int64> %x %y
718
719
720
721
    ssa!            ((vm, hybrid_fix_part_insts_v1) <int64> blk_check_res);
    inst!           ((vm, hybrid_fix_part_insts_v1) blk_check_add:
        blk_check_res = BINOP (BinOp::Add) blk_check_x blk_check_y
    );
qinsoon's avatar
qinsoon committed
722
723

    // CCALL exit(%res)
724
    let blk_check_ccall = gen_ccall_exit(blk_check_res.clone(), &mut hybrid_fix_part_insts_v1, &vm);
qinsoon's avatar
qinsoon committed
725

726
    // RET
727
    inst!           ((vm, hybrid_fix_part_insts_v1) blk_check_ret:
728
        RET
729
    );
qinsoon's avatar
qinsoon committed
730

731
732
733
734
735
736
737
    define_block!   ((vm, hybrid_fix_part_insts_v1) blk_check(blk_check_a) {
        blk_check_getiref,
        blk_check_getfield,
        blk_check_load,
        blk_check_getfield2,
        blk_check_load2,
        blk_check_add,
qinsoon's avatar
qinsoon committed
738
739
740
741
        blk_check_ccall,
        blk_check_ret
    });

742
743
744
745
    define_func_ver!((vm) hybrid_fix_part_insts_v1 (entry: blk_entry) {
        blk_entry,
        blk_check
    });
qinsoon's avatar
qinsoon committed
746

qinsoon's avatar
qinsoon committed
747
748
749
750
751
752
753
754
755
    vm
}

#[test]
fn test_hybrid_var_part() {
    VM::start_logging_trace();

    let vm = Arc::new(hybrid_var_part_insts());

qinsoon's avatar
qinsoon committed
756
    let compiler = Compiler::new(CompilerPolicy::default(), &vm);
qinsoon's avatar
qinsoon committed
757
758
759
760
761
762
763
764
765
766
767

    let func_id = vm.id_of("hybrid_var_part_insts");
    {
        let funcs = vm.funcs().read().unwrap();
        let func = funcs.get(&func_id).unwrap().read().unwrap();
        let func_vers = vm.func_vers().read().unwrap();
        let mut func_ver = func_vers.get(&func.cur_ver.unwrap()).unwrap().write().unwrap();

        compiler.compile(&mut func_ver);
    }

qinsoon's avatar
qinsoon committed
768
    vm.set_primordial_thread(func_id, true, vec![]);
qinsoon's avatar
qinsoon committed
769
770
    backend::emit_context(&vm);

qinsoon's avatar
qinsoon committed
771
    let executable = aot::link_primordial(vec!["hybrid_var_part_insts".to_string()], "hybrid_var_part_insts_test", &vm);
qinsoon's avatar
qinsoon committed
772
    let output = linkutils::exec_path_nocheck(executable);
qinsoon's avatar
qinsoon committed
773
774
775
776
777
778
779
780
781
782
783

    assert!(output.status.code().is_some());

    let ret_code = output.status.code().unwrap();
    println!("return code: {}", ret_code);
    assert!(ret_code == 20);
}

pub fn hybrid_var_part_insts() -> VM {
    let vm = VM::new();

784
785
786
787
788
789
    typedef!        ((vm) int64      = mu_int(64));
    typedef!        ((vm) my_hybrid  = mu_hybrid(int64, int64)(int64));
    typedef!        ((vm) ref_hybrid  = mu_ref(my_hybrid));
    typedef!        ((vm) iref_hybrid = mu_iref(my_hybrid));
    typedef!        ((vm) iref_int64  = mu_iref(int64));
    typedef!        ((vm) int1       = mu_int(1));
qinsoon's avatar
qinsoon committed
790

791
792
793
794
795
796
    constdef!       ((vm) <int64> int64_0 = Constant::Int(0));
    constdef!       ((vm) <int64> int64_1 = Constant::Int(1));
    constdef!       ((vm) <int64> int64_2 = Constant::Int(2));
    constdef!       ((vm) <int64> int64_3 = Constant::Int(3));
    constdef!       ((vm) <int64> int64_4 = Constant::Int(4));
    constdef!       ((vm) <int64> int64_10 = Constant::Int(10));
qinsoon's avatar
qinsoon committed
797

798
799
800
    funcsig!        ((vm) noparam_noret_sig = () -> ());
    funcdecl!       ((vm) <noparam_noret_sig> hybrid_var_part_insts);
    funcdef!        ((vm) <noparam_noret_sig> hybrid_var_part_insts VERSION hybrid_var_part_insts_v1);
qinsoon's avatar
qinsoon committed
801
802

    // %entry():
803
    block!          ((vm, hybrid_var_part_insts_v1) blk_entry);
qinsoon's avatar
qinsoon committed
804
805

    // %a = NEWHYBRID <@my_hybrid @int64> @int64_10
806
807
808
809
810
    ssa!            ((vm, hybrid_var_part_insts_v1) <ref_hybrid> a);
    consta!         ((vm, hybrid_var_part_insts_v1) int64_10_local = int64_10);
    inst!           ((vm, hybrid_var_part_insts_v1) blk_entry_newhybrid:
        a = NEWHYBRID <my_hybrid> int64_10_local
    );
qinsoon's avatar
qinsoon committed
811
812

    // %iref_a = GETIREF <@int64> %a
813
814
815
816
    ssa!            ((vm, hybrid_var_part_insts_v1) <iref_hybrid> iref_a);
    inst!           ((vm, hybrid_var_part_insts_v1) blk_entry_getiref:
        iref_a = GETIREF a
    );
qinsoon's avatar
qinsoon committed
817
818

    // %iref_var = GETVARPARTIREF <@my_hybrid> %iref_a
819
820
821
822
    ssa!            ((vm, hybrid_var_part_insts_v1) <iref_int64> iref_var);
    inst!           ((vm, hybrid_var_part_insts_v1) blk_entry_getvarpart:
        iref_var = GETVARPARTIREF iref_a (is_ptr: false)
    );
qinsoon's avatar
qinsoon committed
823
824

    // %var0 = SHIFTIREF <@int64> %iref_var %int64_0
825
826
827
828
829
    ssa!            ((vm, hybrid_var_part_insts_v1) <iref_int64> var0);
    consta!         ((vm, hybrid_var_part_insts_v1) int64_0_local = int64_0);
    inst!           ((vm, hybrid_var_part_insts_v1) blk_entry_shift0:
        var0 = SHIFTIREF iref_var int64_0_local (is_ptr: false)
    );
qinsoon's avatar
qinsoon committed
830
831

    // STORE <@int64> %var0 @int64_10
832
833
834
    inst!           ((vm, hybrid_var_part_insts_v1) blk_entry_store0:
        STORE var0 int64_10_local (is_ptr: false, order: MemoryOrder::Relaxed)
    );
qinsoon's avatar
qinsoon committed
835
836

    // %var4 = SHIFTIREF <@int64> %iref_var %int64_4
837
838
839
840
841
    ssa!            ((vm, hybrid_var_part_insts_v1) <iref_int64> var4);
    consta!         ((vm, hybrid_var_part_insts_v1) int64_4_local = int64_4);
    inst!           ((vm, hybrid_var_part_insts_v1) blk_entry_shift4:
        var4 = SHIFTIREF iref_var int64_4_local (is_ptr: false)
    );
qinsoon's avatar
qinsoon committed
842
843

    // STORE <@int64> %var4 @int64_10
844
845
846
    inst!           ((vm, hybrid_var_part_insts_v1) blk_entry_store4:
        STORE var4 int64_10_local (is_ptr: false, order: MemoryOrder::Relaxed)
    );
qinsoon's avatar
qinsoon committed
847
848

    // BRANCH %check(%a)
849
850
851
852
    block!          ((vm, hybrid_var_part_insts_v1) blk_check);
    inst!           ((vm, hybrid_var_part_insts_v1) blk_entry_branch:
        BRANCH blk_check(a)
    );
qinsoon's avatar
qinsoon committed
853

854
855
856
857
858
859
860
861
    define_block!   ((vm, hybrid_var_part_insts_v1) blk_entry() {
        blk_entry_newhybrid,
        blk_entry_getiref,
        blk_entry_getvarpart,
        blk_entry_shift0,
        blk_entry_store0,
        blk_entry_shift4,
        blk_entry_store4,
qinsoon's avatar
qinsoon committed
862
863
864
865
        blk_entry_branch
    });

    // %check(%a):
866
    ssa!            ((vm, hybrid_var_part_insts_v1) <ref_hybrid> blk_check_a);
qinsoon's avatar
qinsoon committed
867
868
869

    // BRANCH %head (<@int64> sum, <@int64> n, <@int64> %i, <@ref_hybrid> %a)
    //                        0             10            0
870
871
872
873
    block!          ((vm, hybrid_var_part_insts_v1) blk_head);
    inst!           ((vm, hybrid_var_part_insts_v1) blk_check_branch:
        BRANCH blk_head (int64_0_local, int64_10_local, int64_0_local, blk_check_a)
    );
qinsoon's avatar
qinsoon committed
874

875
876
    define_block!   ((vm, hybrid_var_part_insts_v1) blk_check(blk_check_a) {
        blk_check_branch
qinsoon's avatar
qinsoon committed
877
878
879
    });

    // %head(%sum, %n, %i, %a)
880
881
882
883
    ssa!            ((vm, hybrid_var_part_insts_v1) <int64> blk_head_sum);
    ssa!            ((vm, hybrid_var_part_insts_v1) <int64> blk_head_n);
    ssa!            ((vm, hybrid_var_part_insts_v1) <int64> blk_head_i);
    ssa!            ((vm, hybrid_var_part_insts_v1) <int64> blk_head_a);
qinsoon's avatar
qinsoon committed
884
885

    // %cond = SLT <@int64> %i %n
886
887
888
889
    ssa!            ((vm, hybrid_var_part_insts_v1) <int1> blk_head_cond);
    inst!           ((vm, hybrid_var_part_insts_v1) blk_head_slt:
        blk_head_cond = CMPOP (CmpOp::SLT) blk_head_i blk_head_n
    );
qinsoon's avatar
qinsoon committed
890
891

    // BRANCH2 %cond %body(%sum, %n, %i, %a) %exit(%sum)
892
893
894
895
896
897
898
899
    block!          ((vm, hybrid_var_part_insts_v1) blk_body);
    block!          ((vm, hybrid_var_part_insts_v1) blk_exit);
    inst!           ((vm, hybrid_var_part_insts_v1) blk_head_branch2:
        BRANCH2 (blk_head_cond, blk_head_sum, blk_head_n, blk_head_i, blk_head_a)
            IF (OP 0)
            THEN blk_body (vec![1, 2, 3, 4]) WITH 0.9f32,
            ELSE blk_exit (vec![1])
    );
qinsoon's avatar
qinsoon committed
900

901
902
903
    define_block!   ((vm, hybrid_var_part_insts_v1) blk_head (blk_head_sum, blk_head_n, blk_head_i, blk_head_a) {
        blk_head_slt,
        blk_head_branch2
qinsoon's avatar
qinsoon committed
904
905
906
    });

    // %body(%sum, %n, %i, %a):
907
908
909
910
    ssa!            ((vm, hybrid_var_part_insts_v1) <int64> blk_body_sum);
    ssa!            ((vm, hybrid_var_part_insts_v1) <int64> blk_body_n);
    ssa!            ((vm, hybrid_var_part_insts_v1) <int64> blk_body_i);
    ssa!            ((vm, hybrid_var_part_insts_v1) <int64> blk_body_a);
qinsoon's avatar
qinsoon committed
911
912

    // %blk_body_iref_a = GETIREF <@my_hybrid> a
913
914
915
916
    ssa!            ((vm, hybrid_var_part_insts_v1) <iref_hybrid> blk_body_iref_a);
    inst!           ((vm, hybrid_var_part_insts_v1) blk_body_getiref:
        blk_body_iref_a = GETIREF blk_body_a
    );
qinsoon's avatar
qinsoon committed
917
918

    // %blk_body_iref_var = GETVARPARTIREF <@my_hybrid> %blk_body_iref_a
919
920
921
922
    ssa!            ((vm, hybrid_var_part_insts_v1) <iref_int64> blk_body_iref_var);
    inst!           ((vm, hybrid_var_part_insts_v1) blk_body_getvarpart:
        blk_body_iref_var = GETVARPARTIREF blk_body_iref_a (is_ptr: false)
    );
qinsoon's avatar
qinsoon committed
923
924

    // %blk_body_iref_var_i = SHIFTIREF <@int64> %blk_body_iref_var %i
925
926
927
928
    ssa!            ((vm, hybrid_var_part_insts_v1) <iref_int64> blk_body_iref_var_i);
    inst!           ((vm, hybrid_var_part_insts_v1) blk_body_shiftiref:
        blk_body_iref_var_i = SHIFTIREF blk_body_iref_var blk_body_i (is_ptr: false)
    );
qinsoon's avatar
qinsoon committed
929
930

    // %blk_body_ele = LOAD <@int64> %blk_body_iref_var_i
931
932
933
934
    ssa!            ((vm, hybrid_var_part_insts_v1) <int64> blk_body_ele);
    inst!           ((vm, hybrid_var_part_insts_v1) blk_body_load:
        blk_body_ele = LOAD blk_body_iref_var_i (is_ptr: false, order: MemoryOrder::Relaxed)
    );
qinsoon's avatar
qinsoon committed
935
936

    // %blk_body_sum2 = ADD <@int64> %blk_body_sum %blk_body_ele
937
938
939
940
    ssa!            ((vm, hybrid_var_part_insts_v1) <int64> blk_body_sum2);
    inst!           ((vm, hybrid_var_part_insts_v1) blk_body_add:
        blk_body_sum2 = BINOP (BinOp::Add) blk_body_sum blk_body_ele
    );
qinsoon's avatar
qinsoon committed
941
942

    // %blk_body_i2 = ADD <@int64> %blk_body_i @int64_1
943
944
945
946
947
    ssa!            ((vm, hybrid_var_part_insts_v1) <int64> blk_body_i2);
    consta!         ((vm, hybrid_var_part_insts_v1) int64_1_local = int64_1);
    inst!           ((vm, hybrid_var_part_insts_v1) blk_body_add2:
        blk_body_i2 = BINOP (BinOp::Add) blk_body_i int64_1_local
    );
qinsoon's avatar
qinsoon committed
948
949

    // BRANCH1 %head (%sum2, %n, %i2, %a)
950
951
952
    inst!           ((vm, hybrid_var_part_insts_v1) blk_body_branch:
        BRANCH blk_head (blk_body_sum2, blk_body_n, blk_body_i2, blk_body_a)
    );
qinsoon's avatar
qinsoon committed
953

954
955
956
957
958
959
960
961
    define_block!   ((vm, hybrid_var_part_insts_v1) blk_body(blk_body_sum, blk_body_n, blk_body_i, blk_body_a) {
        blk_body_getiref,
        blk_body_getvarpart,
        blk_body_shiftiref,
        blk_body_load,
        blk_body_add,
        blk_body_add2,
        blk_body_branch
qinsoon's avatar
qinsoon committed
962
963
964
    });

    // %exit(%sum):
965
    ssa!            ((vm, hybrid_var_part_insts_v1) <int64> blk_exit_sum);
qinsoon's avatar
qinsoon committed
966

967
    let blk_exit_exit = gen_ccall_exit(blk_exit_sum.clone(), &mut hybrid_var_part_insts_v1, &vm);
qinsoon's avatar
qinsoon committed
968

969
    // RET
970
    inst!           ((vm, hybrid_var_part_insts_v1) blk_exit_ret:
971
        RET
972
    );
qinsoon's avatar
qinsoon committed
973

974
975
976
    define_block!   ((vm, hybrid_var_part_insts_v1) blk_exit(blk_exit_sum) {
        blk_exit_exit,
        blk_exit_ret
qinsoon's avatar
qinsoon committed
977
978
    });

979
980
981
982
983
984
985
    define_func_ver!((vm) hybrid_var_part_insts_v1 (entry: blk_entry) {
        blk_entry,
        blk_check,
        blk_head,
        blk_body,
        blk_exit
    });
qinsoon's avatar
qinsoon committed
986

987
    vm
988
}
qinsoon's avatar
qinsoon committed
989
990
991

#[test]
fn test_shift_iref_ele_4bytes() {
qinsoon's avatar
qinsoon committed
992
    let lib = linkutils::aot::compile_fnc("shift_iref_ele_4bytes", &shift_iref_ele_4bytes);
qinsoon's avatar
qinsoon committed
993
994
995
996
997
998
999
1000

    unsafe {
        let shift_iref_ele_4bytes : libloading::Symbol<unsafe extern fn(u64, u64) -> u64> = lib.get(b"shift_iref_ele_4bytes").unwrap();

        let res = shift_iref_ele_4bytes(0, 0);
        println!("shift_iref_ele_4bytes(0, 0) = {}", res);
        assert_eq!(res, 0);

For faster browsing, not all history is shown. View entire blame