GitLab will be upgraded on June 2nd 2020 at 2.00 pm (AEDT) to 3.00 pm (AEDT) due to Critical Security Patch Availability. During the update, GitLab and Mattermost services will not be available. If you have any concerns with this, please talk to local Gitlab admin team.

Using Mu IR to give test inputs and read outputs: Bin Op tests work now.

parent c5863f83
# Copyright 2017 The Australian National University # Copyright 2017 The Australian National University
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
# You may obtain a copy of the License at # You may obtain a copy of the License at
# #
# http://www.apache.org/licenses/LICENSE-2.0 # http://www.apache.org/licenses/LICENSE-2.0
# #
# Unless required by applicable law or agreed to in writing, software # Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, # distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
[package] [package]
name = "mu" name = "mu"
version = "0.0.1" version = "0.0.1"
...@@ -26,6 +26,7 @@ doctest = false ...@@ -26,6 +26,7 @@ doctest = false
default = ["aot"] default = ["aot"]
aot = [] aot = []
jit = [] jit = []
sel4-rumprun = []
[build-dependencies] [build-dependencies]
gcc = "0.3" gcc = "0.3"
......
...@@ -43,4 +43,23 @@ fn main() { ...@@ -43,4 +43,23 @@ fn main() {
gcc::Config::new().flag("-O3").flag("-c") gcc::Config::new().flag("-O3").flag("-c")
.file("src/runtime/swap_stack_aarch64_sysv.S") .file("src/runtime/swap_stack_aarch64_sysv.S")
.compile("libswap_stack.a"); .compile("libswap_stack.a");
}
#[cfg(feature = "sel4-rumprun")]
#[cfg(target_arch = "x86_64")]
fn main() {
let mut compiler_name = String::new();
compiler_name.push_str("x86_64-rumprun-netbsd-gcc");
gcc::Config::new().flag("-O3").flag("-c")
.compiler(Path::new(compiler_name.as_str()))
.file("src/runtime/runtime_x64_sel4_rumprun_sysv.c")
.compile("libruntime.a");
gcc::Config::new().flag("-O3").flag("-c")
.compiler(Path::new(compiler_name.as_str()))
.file("src/runtime/swap_stack_x64_sysv.S")
.compile("libswap_stack.a");
gcc::Config::new().flag("-O3").flag("-c")
.compiler(Path::new(compiler_name.as_str()))
.file("c_helpers.c")
.compile("libc_helpers.a");
} }
\ No newline at end of file
This diff is collapsed.
...@@ -142,7 +142,8 @@ impl Instruction { ...@@ -142,7 +142,8 @@ impl Instruction {
| CommonInst_Pin(_) | CommonInst_Pin(_)
| CommonInst_Unpin(_) | CommonInst_Unpin(_)
| Move(_) | Move(_)
| PrintHex(_) => None | PrintHex(_)
| SetRetval(_) => None
} }
} }
...@@ -357,7 +358,8 @@ pub enum Instruction_ { ...@@ -357,7 +358,8 @@ pub enum Instruction_ {
// internal use: mov from ops[0] to value // internal use: mov from ops[0] to value
Move(OpIndex), Move(OpIndex),
// internal use: print op as hex value // internal use: print op as hex value
PrintHex(OpIndex) PrintHex(OpIndex),
SetRetval(OpIndex)
} }
impl Instruction_ { impl Instruction_ {
...@@ -484,7 +486,9 @@ impl Instruction_ { ...@@ -484,7 +486,9 @@ impl Instruction_ {
// move // move
&Instruction_::Move(from) => format!("MOVE {}", ops[from]), &Instruction_::Move(from) => format!("MOVE {}", ops[from]),
// print hex // print hex
&Instruction_::PrintHex(i) => format!("PRINTHEX {}", ops[i]) &Instruction_::PrintHex(i) => format!("PRINTHEX {}", ops[i]),
// set retval
&Instruction_::SetRetval(val) => format!("SETRETVAL {}", ops[val])
} }
} }
} }
......
...@@ -47,7 +47,8 @@ pub fn is_terminal_inst(inst: &Instruction_) -> bool { ...@@ -47,7 +47,8 @@ pub fn is_terminal_inst(inst: &Instruction_) -> bool {
| &CommonInst_Pin(_) | &CommonInst_Pin(_)
| &CommonInst_Unpin(_) | &CommonInst_Unpin(_)
| &Move(_) | &Move(_)
| &PrintHex(_) => false, | &PrintHex(_)
| &SetRetval(_) => false,
&Return(_) &Return(_)
| &ThreadExit | &ThreadExit
| &Throw(_) | &Throw(_)
...@@ -114,7 +115,8 @@ pub fn has_side_effect(inst: &Instruction_) -> bool { ...@@ -114,7 +115,8 @@ pub fn has_side_effect(inst: &Instruction_) -> bool {
&CommonInst_Pin(_) => true, &CommonInst_Pin(_) => true,
&CommonInst_Unpin(_) => true, &CommonInst_Unpin(_) => true,
&Move(_) => false, &Move(_) => false,
&PrintHex(_) => true &PrintHex(_) => true,
&SetRetval(_) => true
} }
} }
...@@ -164,6 +166,7 @@ pub fn is_potentially_excepting_instruction(inst: &Instruction_) -> bool { ...@@ -164,6 +166,7 @@ pub fn is_potentially_excepting_instruction(inst: &Instruction_) -> bool {
| &CommonInst_Pin(_) | &CommonInst_Pin(_)
| &CommonInst_Unpin(_) | &CommonInst_Unpin(_)
| &Move(_) | &Move(_)
| &PrintHex(_) => false | &PrintHex(_)
| &SetRetval(_) => false
} }
} }
\ No newline at end of file
...@@ -80,7 +80,8 @@ pub enum OpCode { ...@@ -80,7 +80,8 @@ pub enum OpCode {
CommonInst_Unpin, CommonInst_Unpin,
Move, Move,
PrintHex PrintHex,
SetRetval
} }
pub fn pick_op_code_for_ssa(ty: &P<MuType>) -> OpCode { pub fn pick_op_code_for_ssa(ty: &P<MuType>) -> OpCode {
...@@ -392,5 +393,6 @@ pub fn pick_op_code_for_inst(inst: &Instruction) -> OpCode { ...@@ -392,5 +393,6 @@ pub fn pick_op_code_for_inst(inst: &Instruction) -> OpCode {
Instruction_::CommonInst_Unpin(_) => OpCode::CommonInst_Unpin, Instruction_::CommonInst_Unpin(_) => OpCode::CommonInst_Unpin,
Instruction_::Move(_) => OpCode::Move, Instruction_::Move(_) => OpCode::Move,
Instruction_::PrintHex(_) => OpCode::PrintHex, Instruction_::PrintHex(_) => OpCode::PrintHex,
Instruction_::SetRetval(_) => OpCode::SetRetval,
} }
} }
// Copyright 2017 The Australian National University // Copyright 2017 The Australian National University
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // You may obtain a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // http://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#![warn(unused_imports)] #![warn(unused_imports)]
#![warn(unreachable_code)] #![warn(unreachable_code)]
...@@ -1179,6 +1179,24 @@ impl <'a> InstructionSelection { ...@@ -1179,6 +1179,24 @@ impl <'a> InstructionSelection {
); );
} }
// Runtime Entry
Instruction_::SetRetval(index) => {
trace!("instsel on SETRETVAL");
let ref ops = inst.ops.read().unwrap();
let ref op = ops[index];
assert!(self.match_ireg(op));
let retval = self.emit_ireg(op, f_content, f_context, vm);
self.emit_runtime_entry(
&entrypoints::SET_RETVAL,
vec![op.clone_value()],
None,
Some(node), f_context, vm
);
}
_ => unimplemented!() _ => unimplemented!()
} // main switch } // main switch
}, },
......
...@@ -3028,7 +3028,25 @@ impl CodeGenerator for ASMCodeGen { ...@@ -3028,7 +3028,25 @@ impl CodeGenerator for ASMCodeGen {
ValueLocation::Relocatable(RegGroup::GPR, callsite) ValueLocation::Relocatable(RegGroup::GPR, callsite)
} }
#[cfg(feature = "sel4-rumprun")]
// exactly the same as Linux:
// generating Position-Independent Code using PLT
fn emit_call_near_rel32(&mut self, callsite: String, func: MuName, pe: Option<MuName>) -> ValueLocation {
trace!("emit: call {}", func);
let func = func + "@PLT";
let asm = format!("call {}", symbol(func));
self.add_asm_call(asm, pe);
let callsite_symbol = symbol(callsite.clone());
self.add_asm_symbolic(directive_globl(callsite_symbol.clone()));
self.add_asm_symbolic(format!("{}:", callsite_symbol.clone()));
ValueLocation::Relocatable(RegGroup::GPR, callsite)
}
fn emit_call_near_r64(&mut self, callsite: String, func: &P<Value>, pe: Option<MuName>) -> ValueLocation { fn emit_call_near_r64(&mut self, callsite: String, func: &P<Value>, pe: Option<MuName>) -> ValueLocation {
trace!("emit: call {}", func); trace!("emit: call {}", func);
...@@ -3437,6 +3455,13 @@ fn write_align(f: &mut File, align: ByteSize) { ...@@ -3437,6 +3455,13 @@ fn write_align(f: &mut File, align: ByteSize) {
f.write_fmt(format_args!("\t.align {}\n", n)).unwrap(); f.write_fmt(format_args!("\t.align {}\n", n)).unwrap();
} }
// The alignment is exactly the same as Linux
#[cfg(feature = "sel4-rumprun")]
fn write_align(f: &mut File, align: ByteSize) {
use std::io::Write;
f.write_fmt(format_args!("\t.align {}\n", check_min_align(align))).unwrap();
}
fn write_const(f: &mut File, constant: P<Value>, loc: P<Value>) { fn write_const(f: &mut File, constant: P<Value>, loc: P<Value>) {
use std::io::Write; use std::io::Write;
...@@ -3689,6 +3714,12 @@ pub fn symbol(name: String) -> String { ...@@ -3689,6 +3714,12 @@ pub fn symbol(name: String) -> String {
pub fn symbol(name: String) -> String { pub fn symbol(name: String) -> String {
format!("_{}", name) format!("_{}", name)
} }
// same as Linux
#[cfg(feature = "sel4-rumprun")]
pub fn symbol(name: String) -> String {
name
}
#[allow(dead_code)] #[allow(dead_code)]
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
...@@ -3700,6 +3731,12 @@ pub fn pic_symbol(name: String) -> String { ...@@ -3700,6 +3731,12 @@ pub fn pic_symbol(name: String) -> String {
pub fn pic_symbol(name: String) -> String { pub fn pic_symbol(name: String) -> String {
symbol(name) symbol(name)
} }
// same as Linux
#[allow(dead_code)]
#[cfg(feature = "sel4-rumprun")]
pub fn pic_symbol(name: String) -> String {
format!("{}@GOTPCREL", name)
}
use compiler::machine_code::CompiledFunction; use compiler::machine_code::CompiledFunction;
......
...@@ -1444,7 +1444,24 @@ impl <'a> InstructionSelection { ...@@ -1444,7 +1444,24 @@ impl <'a> InstructionSelection {
Some(node), f_content, f_context, vm Some(node), f_content, f_context, vm
); );
} }
Instruction_::SetRetval(index) => {
trace!("instsel on SETRETVAL");
let ref ops = inst.ops;
let ref op = ops[index];
assert!(self.match_ireg(op));
let retval = self.emit_ireg(op, f_content, f_context, vm);
self.emit_runtime_entry(
&entrypoints::SET_RETVAL,
vec![op.clone_value()],
None,
Some(node), f_content, f_context, vm
);
}
_ => unimplemented!() _ => unimplemented!()
} // main switch } // main switch
}, },
...@@ -3932,6 +3949,9 @@ impl <'a> InstructionSelection { ...@@ -3932,6 +3949,9 @@ impl <'a> InstructionSelection {
} else if cfg!(target_os = "linux") { } else if cfg!(target_os = "linux") {
let mem = self.get_mem_for_funcref(func_id, vm); let mem = self.get_mem_for_funcref(func_id, vm);
self.backend.emit_mov_r_mem(&tmp, &mem); self.backend.emit_mov_r_mem(&tmp, &mem);
} else if cfg!(feature = "sel4-rumprun") {
let mem = self.get_mem_for_funcref(func_id, vm);
self.backend.emit_mov_r_mem(&tmp, &mem);
} else { } else {
unimplemented!() unimplemented!()
} }
...@@ -4125,6 +4145,25 @@ impl <'a> InstructionSelection { ...@@ -4125,6 +4145,25 @@ impl <'a> InstructionSelection {
let actual_loc = self.make_temporary(f_context, pv.ty.clone(), vm); let actual_loc = self.make_temporary(f_context, pv.ty.clone(), vm);
self.emit_move_value_to_value(&actual_loc, &got_loc); self.emit_move_value_to_value(&actual_loc, &got_loc);
self.make_memory_op_base_offset(&actual_loc, 0, types::get_referent_ty(&pv.ty).unwrap(), vm)
} else if cfg!(feature = "sel4-rumprun") {
// for a(%RIP), we need to load its address from a@GOTPCREL(%RIP)
// then load from the address.
// asm_backend will emit a@GOTPCREL(%RIP) for a(%RIP)
let got_loc = P(Value {
hdr: MuEntityHeader::unnamed(vm.next_id()),
ty: pv.ty.clone(),
v: Value_::Memory(MemoryLocation::Symbolic {
base: Some(x86_64::RIP.clone()),
label: pv.name().unwrap(),
is_global: true
})
});
// mov (got_loc) -> actual_loc
let actual_loc = self.make_temporary(f_context, pv.ty.clone(), vm);
self.emit_move_value_to_value(&actual_loc, &got_loc);
self.make_memory_op_base_offset(&actual_loc, 0, types::get_referent_ty(&pv.ty).unwrap(), vm) self.make_memory_op_base_offset(&actual_loc, 0, types::get_referent_ty(&pv.ty).unwrap(), vm)
} else { } else {
unimplemented!() unimplemented!()
...@@ -4695,7 +4734,9 @@ impl <'a> InstructionSelection { ...@@ -4695,7 +4734,9 @@ impl <'a> InstructionSelection {
layout[index] as i32 layout[index] as i32
} }
// Primordial function name was added as part of the callsite label \
// because it avoids conflicts between labels of different tests
fn new_callsite_label(&mut self, cur_node: Option<&TreeNode>) -> String { fn new_callsite_label(&mut self, cur_node: Option<&TreeNode>) -> String {
let ret = { let ret = {
if cur_node.is_some() { if cur_node.is_some() {
......
...@@ -529,6 +529,7 @@ pub fn estimate_insts_for_ir(inst: &Instruction) -> usize { ...@@ -529,6 +529,7 @@ pub fn estimate_insts_for_ir(inst: &Instruction) -> usize {
// others // others
Move(_) => 0, Move(_) => 0,
PrintHex(_) => 10, PrintHex(_) => 10,
SetRetval(_) => 10,
ExnInstruction{ref inner, ..} => estimate_insts_for_ir(&inner) ExnInstruction{ref inner, ..} => estimate_insts_for_ir(&inner)
} }
} }
...@@ -32,3 +32,14 @@ fn main() { ...@@ -32,3 +32,14 @@ fn main() {
fn main() { fn main() {
gcc::compile_library("libgc_clib_aarch64.a", &["src/heap/gc/clib_aarch64.S"]); gcc::compile_library("libgc_clib_aarch64.a", &["src/heap/gc/clib_aarch64.S"]);
} }
#[cfg(feature = "sel4-rumprun")]
#[cfg(target_arch = "x86_64")]
fn main() {
let mut compiler_name = String::new();
compiler_name.push_str("x86_64-rumprun-netbsd-gcc");
gcc::Config::new().flag("-O3").flag("-c")
.compiler(Path::new(compiler_name.as_str()))
.file("src/heap/gc/clib_x64_sel4_rumprun.c")
.compile("libgc_clib_x64_sel4_rumprun.a");
}
\ No newline at end of file
// 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.
#include <inttypes.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
void* malloc_zero(size_t size) {
void* ret = malloc(size);
memset(ret, 0, size);
return ret;
}
uintptr_t immmix_get_stack_ptr() {
uintptr_t rsp;
// get current rsp, rbp (this C func frame)
__asm__(
"mov %%rsp, %0 \n"
: "=rm" (rsp)
);
return rsp;
}
int get_registers_count() {
return 16;
}
uintptr_t* get_registers () {
uintptr_t rax, rbx, rcx, rdx, rbp, rsp, rsi, rdi, r8, r9, r10, r11, r12, r13, r14, r15;
__asm__(
"mov %%rax, %0 \n"
"mov %%rbx, %1 \n"
"mov %%rcx, %2 \n"
"mov %%rdx, %3 \n"
"mov %%rbp, %4 \n"
"mov %%rsp, %5 \n"
"mov %%rsi, %5 \n"
"mov %%rdi, %6 \n"
"mov %%r8, %7 \n"
"mov %%r9, %8 \n"
"mov %%r10, %10\n"
"mov %%r11, %11\n"
"mov %%r12, %12\n"
"mov %%r13, %13\n"
"mov %%r14, %14\n"
"mov %%r15, %15\n"
: "=m" (rax),
"=m" (rbx),
"=m" (rcx),
"=m" (rdx),
"=m" (rbp),
"=m" (rsp),
"=m" (rsi),
"=m" (rdi),
"=m" (r8),
"=m" (r9),
"=m" (r10),
"=m" (r11),
"=m" (r12),
"=m" (r13),
"=m" (r14),
"=m" (r15)
:
:
);
uintptr_t* ret = (uintptr_t*) malloc(sizeof(uintptr_t) * 16);
ret[0] = rax;
ret[1] = rbx;
ret[2] = rcx;
ret[3] = rdx;
ret[4] = rbp;
ret[5] = rsp;
ret[6] = rsi;
ret[7] = rdi;
ret[8] = r8;
ret[9] = r9;
ret[10] = r10;
ret[11] = r11;
ret[12] = r12;
ret[13] = r13;
ret[14] = r14;
ret[15] = r15;
return ret;
}
// __thread uintptr_t low_water_mark;
int lwm_initialized = 0;
static pthread_key_t low_water_mark;
void set_low_water_mark () {
uintptr_t rsp;
if(lwm_initialized == 0){
lwm_initialized = 1;
int result = pthread_key_create(&low_water_mark, NULL);
if(result != 0){
printf("set_low_water_mark(): PThread key create failed with error code = %d\n", result);
assert(0);
}
}
// get current rsp, rbp (this C func frame)
__asm__(
"mov %%rsp, %0 \n"
: "=rm" (rsp)
);
int result = pthread_setspecific(low_water_mark, (const void *) rsp);
if(result != 0){
printf("set_low_water_mark(): PThread set specific failed with error code = %d\n", result);
assert(0);
}
}
uintptr_t get_low_water_mark() {
if(lwm_initialized == 0){
printf("get_low_water_mark(): PThread key MUST be initialized before first use!!\n");
}
void * result = pthread_getspecific(low_water_mark);
if(result == NULL){
printf("get_low_water_mark(): NO pthread key found for current thread!!\n");
assert(0);
}
return (uintptr_t) result;
}
...@@ -87,6 +87,18 @@ extern "C" { ...@@ -87,6 +87,18 @@ extern "C" {
fn get_registers_count() -> i32; fn get_registers_count() -> i32;
} }
#[cfg(target_arch = "x86_64")]
#[cfg(feature = "sel4-rumprun")]
#[link(name = "gc_clib_x64_sel4_rumprun")]
extern "C" {
pub fn malloc_zero(size: usize) -> *const c_void;
fn immmix_get_stack_ptr() -> Address;
pub fn set_low_water_mark();
fn get_low_water_mark() -> Address;
fn get_registers() -> *const Address;
fn get_registers_count() -> i32;
}
pub fn stack_scan() -> Vec<ObjectReference> { pub fn stack_scan() -> Vec<ObjectReference> {
trace!("stack scanning..."); trace!("stack scanning...");
let stack_ptr : Address = unsafe {immmix_get_stack_ptr()}; let stack_ptr : Address = unsafe {immmix_get_stack_ptr()};
......
# 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.
// This file provides a template so that we can define functions in ASM and also
// let the symbols be recognised in both Linux and OSX
#define CNAME(n) n
.macro begin_func n
.text
.globl CNAME(\n)
.type CNAME(\n),@function
.balign 16
CNAME(\n):
.endm
.macro end_func n
.size CNAME(\n), .-CNAME(\n)
.endm
; vim: ft=asm
...@@ -42,7 +42,19 @@ lazy_static! { ...@@ -42,7 +42,19 @@ lazy_static! {
aot: ValueLocation::Relocatable(RegGroup::GPR, String::from("muentry_get_thread_local")), aot: ValueLocation::Relocatable(RegGroup::GPR, String::from("muentry_get_thread_local")),
jit: RwLock::new(None), jit: RwLock::new(None),
}; };
// impl: runtime_x64_sysv.c
// decl: thread.rs
pub static ref SET_RETVAL : RuntimeEntrypoint = RuntimeEntrypoint {
sig: P(MuFuncSig {
hdr: MuEntityHeader::unnamed(ir::new_internal_id()),
ret_tys: vec![],
arg_tys: vec![UINT32_TYPE.clone()]
}),
aot: ValueLocation::Relocatable(RegGroup::GPR, String::from("muentry_set_retval")),
jit: RwLock::new(None)
};
// impl: swap_stack_x64_macos.s // impl: swap_stack_x64_macos.s
// decl: thread.rs // decl: thread.rs
pub static ref SWAP_BACK_TO_NATIVE_STACK : RuntimeEntrypoint = RuntimeEntrypoint { pub static ref SWAP_BACK_TO_NATIVE_STACK : RuntimeEntrypoint = RuntimeEntrypoint {
......
// 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.
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>
extern void* vm;
extern void mu_main(char*, int, char**);
extern int32_t c_check_result();
int main(int argc, char** argv) {
char* serialize_vm = (char*) &vm;
mu_main(serialize_vm, argc, argv);
assert(c_check_result() == 0);
}
...@@ -21,6 +21,7 @@ use utils::Address; ...@@ -21,6 +21,7 @@ use utils::Address;
use std::fmt; use std::fmt;
use std::os::raw::c_int;