Commit 38d18dda authored by qinsoon's avatar qinsoon

start using 8/16/32 bits registers

1. compiler knows all the registers
2. but only 64bits register is a color (for reg alloc)
3. backend records the length of GPR for each operand during instruction
selection
4. after reg alloc, when replacing temp with a color, find corresponding
GPR for the length recorded before
parent 5c0bdb9f
......@@ -36,11 +36,11 @@ lazy_static! {
};
}
pub const MACHINE_ID_START : usize = 0;
pub const MACHINE_ID_END : usize = 100;
pub const MACHINE_ID_END : usize = 200;
pub const INTERNAL_ID_START: usize = 101;
pub const INTERNAL_ID_END : usize = 200;
pub const USER_ID_START : usize = 201;
pub const INTERNAL_ID_START: usize = 201;
pub const INTERNAL_ID_END : usize = 500;
pub const USER_ID_START : usize = 1001;
#[deprecated]
#[allow(dead_code)]
......
......@@ -75,6 +75,23 @@ impl MuType {
_ => None
}
}
pub fn get_int_length(&self) -> Option<usize> {
use types::MuType_::*;
match self.v {
Int(len) => Some(len),
Ref(_)
| IRef(_)
| WeakRef(_)
| UPtr(_)
| ThreadRef
| StackRef
| Tagref64
| FuncRef(_)
| UFuncPtr(_) => Some(64),
_ => None
}
}
}
pub type StructTag = MuName;
......@@ -496,6 +513,6 @@ pub struct MuFuncSig {
impl fmt::Display for MuFuncSig {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "[{}] -> [{}]", vec_utils::as_str(&self.ret_tys), vec_utils::as_str(&self.arg_tys))
write!(f, "[{}] -> [{}]", vec_utils::as_str(&self.arg_tys), vec_utils::as_str(&self.ret_tys))
}
}
This diff is collapsed.
......@@ -21,6 +21,18 @@ use compiler::backend::RegGroup;
use std::collections::HashMap;
macro_rules! GPR_ALIAS {
($alias: ident: ($id64: expr, $r64: ident) -> $r32: ident, $r16: ident, $r8l: ident, $r8h: ident) => {
lazy_static!{
pub static ref $r64 : P<Value> = GPR!($id64, stringify!($r64), UINT64_TYPE);
pub static ref $r32 : P<Value> = GPR!($id64 +1, stringify!($r32), UINT32_TYPE);
pub static ref $r16 : P<Value> = GPR!($id64 +2, stringify!($r16), UINT16_TYPE);
pub static ref $r8l : P<Value> = GPR!($id64 +3, stringify!($r8l), UINT8_TYPE);
pub static ref $r8h : P<Value> = GPR!($id64 +4, stringify!($r8h), UINT8_TYPE);
pub static ref $alias : [P<Value>; 5] = [$r64.clone(), $r32.clone(), $r16.clone(), $r8l.clone(), $r8h.clone()];
}
};
($alias: ident: ($id64: expr, $r64: ident) -> $r32: ident, $r16: ident, $r8: ident) => {
lazy_static!{
pub static ref $r64 : P<Value> = GPR!($id64, stringify!($r64), UINT64_TYPE);
......@@ -65,26 +77,26 @@ macro_rules! FPR {
};
}
GPR_ALIAS!(RAX_ALIAS: (0, RAX) -> EAX, AX , AL);
GPR_ALIAS!(RCX_ALIAS: (4, RCX) -> ECX, CX , CL);
GPR_ALIAS!(RDX_ALIAS: (8, RDX) -> EDX, DX , DL);
GPR_ALIAS!(RBX_ALIAS: (12,RBX) -> EBX, BX , BL);
GPR_ALIAS!(RSP_ALIAS: (16,RSP) -> ESP, SP , SPL);
GPR_ALIAS!(RBP_ALIAS: (20,RBP) -> EBP, BP , BPL);
GPR_ALIAS!(RSI_ALIAS: (24,RSI) -> ESI, SI , SIL);
GPR_ALIAS!(RDI_ALIAS: (28,RDI) -> EDI, DI , DIL);
GPR_ALIAS!(R8_ALIAS : (32,R8 ) -> R8D, R8W, R8L);
GPR_ALIAS!(R9_ALIAS : (36,R9 ) -> R9D, R9W, R9L);
GPR_ALIAS!(R10_ALIAS: (40,R10) -> R10D,R10W,R10L);
GPR_ALIAS!(R11_ALIAS: (44,R11) -> R11D,R11W,R11L);
GPR_ALIAS!(R12_ALIAS: (48,R12) -> R12D,R12W,R12L);
GPR_ALIAS!(R13_ALIAS: (52,R13) -> R13D,R13W,R13L);
GPR_ALIAS!(R14_ALIAS: (56,R14) -> R14D,R14W,R14L);
GPR_ALIAS!(R15_ALIAS: (60,R15) -> R15D,R15W,R15L);
GPR_ALIAS!(RIP_ALIAS: (64,RIP));
GPR_ALIAS!(RAX_ALIAS: (0, RAX) -> EAX, AX , AL, AH);
GPR_ALIAS!(RCX_ALIAS: (5, RCX) -> ECX, CX , CL, CH);
GPR_ALIAS!(RDX_ALIAS: (10, RDX) -> EDX, DX , DL, DH);
GPR_ALIAS!(RBX_ALIAS: (15,RBX) -> EBX, BX , BL, BH);
GPR_ALIAS!(RSP_ALIAS: (20,RSP) -> ESP, SP , SPL);
GPR_ALIAS!(RBP_ALIAS: (24,RBP) -> EBP, BP , BPL);
GPR_ALIAS!(RSI_ALIAS: (28,RSI) -> ESI, SI , SIL);
GPR_ALIAS!(RDI_ALIAS: (32,RDI) -> EDI, DI , DIL);
GPR_ALIAS!(R8_ALIAS : (36,R8 ) -> R8D, R8W, R8B);
GPR_ALIAS!(R9_ALIAS : (40,R9 ) -> R9D, R9W, R9B);
GPR_ALIAS!(R10_ALIAS: (44,R10) -> R10D,R10W,R10B);
GPR_ALIAS!(R11_ALIAS: (48,R11) -> R11D,R11W,R11B);
GPR_ALIAS!(R12_ALIAS: (52,R12) -> R12D,R12W,R12B);
GPR_ALIAS!(R13_ALIAS: (56,R13) -> R13D,R13W,R13B);
GPR_ALIAS!(R14_ALIAS: (60,R14) -> R14D,R14W,R14B);
GPR_ALIAS!(R15_ALIAS: (64,R15) -> R15D,R15W,R15B);
GPR_ALIAS!(RIP_ALIAS: (68,RIP));
lazy_static! {
pub static ref GPR_ALIAS_LOOKUP_TABLE : HashMap<MuID, Vec<P<Value>>> = {
pub static ref GPR_ALIAS_TABLE : HashMap<MuID, Vec<P<Value>>> = {
let mut ret = HashMap::new();
ret.insert(RAX.id(), RAX_ALIAS.to_vec());
......@@ -107,20 +119,58 @@ lazy_static! {
ret
};
}
pub fn get_gpr_alias(id: MuID, length: usize) -> P<Value> {
let vec = match GPR_ALIAS_LOOKUP_TABLE.get(&id) {
Some(vec) => vec,
None => panic!("didnt find {} as GPR", id)
// e.g. given eax, return rax
pub static ref GPR_ALIAS_LOOKUP : HashMap<MuID, P<Value>> = {
let mut ret = HashMap::new();
for vec in GPR_ALIAS_TABLE.values() {
let colorable = vec[0].clone();
for gpr in vec {
ret.insert(gpr.id(), colorable.clone());
}
}
ret
};
}
pub fn get_alias_for_length(id: MuID, length: usize) -> P<Value> {
if id < FPR_ID_START {
let vec = match GPR_ALIAS_TABLE.get(&id) {
Some(vec) => vec,
None => panic!("didnt find {} as GPR", id)
};
match length {
64 => vec[0].clone(),
32 => vec[1].clone(),
16 => vec[2].clone(),
8 => vec[3].clone(),
1 => vec[3].clone(),
_ => panic!("unexpected length {} for {}", length, vec[0])
}
} else {
for r in ALL_FPRs.iter() {
if r.id() == id {
return r.clone();
}
}
match length {
64 => vec[0].clone(),
32 => vec[1].clone(),
16 => vec[2].clone(),
8 => vec[3].clone(),
_ => panic!("unexpected length: {}", length)
panic!("didnt find {} as FPR", id)
}
}
pub fn get_color_for_precolroed(id: MuID) -> MuID {
if id < FPR_ID_START {
match GPR_ALIAS_LOOKUP.get(&id) {
Some(val) => val.id(),
None => panic!("cannot find GPR {}", id)
}
} else {
// we do not have alias for FPRs
id
}
}
......@@ -160,7 +210,7 @@ lazy_static! {
R11.clone()
];
pub static ref ALL_GPRs : [P<Value>; 15] = [
static ref ALL_GPRs : [P<Value>; 15] = [
RAX.clone(),
RCX.clone(),
RDX.clone(),
......@@ -180,23 +230,25 @@ lazy_static! {
];
}
pub const FPR_ID_START : usize = 100;
lazy_static!{
pub static ref XMM0 : P<Value> = FPR!(70,"xmm0");
pub static ref XMM1 : P<Value> = FPR!(71,"xmm1");
pub static ref XMM2 : P<Value> = FPR!(72,"xmm2");
pub static ref XMM3 : P<Value> = FPR!(73,"xmm3");
pub static ref XMM4 : P<Value> = FPR!(74,"xmm4");
pub static ref XMM5 : P<Value> = FPR!(75,"xmm5");
pub static ref XMM6 : P<Value> = FPR!(76,"xmm6");
pub static ref XMM7 : P<Value> = FPR!(77,"xmm7");
pub static ref XMM8 : P<Value> = FPR!(78,"xmm8");
pub static ref XMM9 : P<Value> = FPR!(79,"xmm9");
pub static ref XMM10 : P<Value> = FPR!(80,"xmm10");
pub static ref XMM11 : P<Value> = FPR!(81,"xmm11");
pub static ref XMM12 : P<Value> = FPR!(82,"xmm12");
pub static ref XMM13 : P<Value> = FPR!(83,"xmm13");
pub static ref XMM14 : P<Value> = FPR!(84,"xmm14");
pub static ref XMM15 : P<Value> = FPR!(85,"xmm15");
pub static ref XMM0 : P<Value> = FPR!(FPR_ID_START, "xmm0");
pub static ref XMM1 : P<Value> = FPR!(FPR_ID_START + 1,"xmm1");
pub static ref XMM2 : P<Value> = FPR!(FPR_ID_START + 2,"xmm2");
pub static ref XMM3 : P<Value> = FPR!(FPR_ID_START + 3,"xmm3");
pub static ref XMM4 : P<Value> = FPR!(FPR_ID_START + 4,"xmm4");
pub static ref XMM5 : P<Value> = FPR!(FPR_ID_START + 5,"xmm5");
pub static ref XMM6 : P<Value> = FPR!(FPR_ID_START + 6,"xmm6");
pub static ref XMM7 : P<Value> = FPR!(FPR_ID_START + 7,"xmm7");
pub static ref XMM8 : P<Value> = FPR!(FPR_ID_START + 8,"xmm8");
pub static ref XMM9 : P<Value> = FPR!(FPR_ID_START + 9,"xmm9");
pub static ref XMM10 : P<Value> = FPR!(FPR_ID_START + 10,"xmm10");
pub static ref XMM11 : P<Value> = FPR!(FPR_ID_START + 11,"xmm11");
pub static ref XMM12 : P<Value> = FPR!(FPR_ID_START + 12,"xmm12");
pub static ref XMM13 : P<Value> = FPR!(FPR_ID_START + 13,"xmm13");
pub static ref XMM14 : P<Value> = FPR!(FPR_ID_START + 14,"xmm14");
pub static ref XMM15 : P<Value> = FPR!(FPR_ID_START + 15,"xmm15");
pub static ref RETURN_FPRs : [P<Value>; 2] = [
XMM0.clone(),
......@@ -235,7 +287,7 @@ lazy_static!{
XMM15.clone(),
];
pub static ref ALL_FPRs : [P<Value>; 16] = [
static ref ALL_FPRs : [P<Value>; 16] = [
XMM0.clone(),
XMM1.clone(),
XMM2.clone(),
......@@ -255,28 +307,16 @@ lazy_static!{
];
}
pub const GPR_COUNT : usize = 16;
pub const FPR_COUNT : usize = 16;
lazy_static! {
pub static ref ALL_MACHINE_REGs : HashMap<MuID, P<Value>> = {
let mut map = HashMap::new();
map.insert(RAX.id(), RAX.clone());
map.insert(RCX.id(), RCX.clone());
map.insert(RDX.id(), RDX.clone());
map.insert(RBX.id(), RBX.clone());
map.insert(RSP.id(), RSP.clone());
map.insert(RBP.id(), RBP.clone());
map.insert(RSI.id(), RSI.clone());
map.insert(RDI.id(), RDI.clone());
map.insert(R8.id(), R8.clone());
map.insert(R9.id(), R9.clone());
map.insert(R10.id(), R10.clone());
map.insert(R11.id(), R11.clone());
map.insert(R12.id(), R12.clone());
map.insert(R13.id(), R13.clone());
map.insert(R14.id(), R14.clone());
map.insert(R15.id(), R15.clone());
for vec in GPR_ALIAS_TABLE.values() {
for reg in vec {
map.insert(reg.id(), reg.clone());
}
}
map.insert(XMM0.id(), XMM0.clone());
map.insert(XMM1.id(), XMM1.clone());
map.insert(XMM2.id(), XMM2.clone());
......@@ -293,7 +333,6 @@ lazy_static! {
map.insert(XMM13.id(), XMM13.clone());
map.insert(XMM14.id(), XMM14.clone());
map.insert(XMM15.id(), XMM15.clone());
map.insert(RIP.id(), RIP.clone());
map
};
......
......@@ -15,6 +15,9 @@ pub const AOT_EMIT_CONTEXT_FILE : &'static str = "context.s";
pub const PROLOGUE_BLOCK_NAME: &'static str = "prologue";
pub const EPILOGUE_BLOCK_NAME: &'static str = "epilogue";
pub type Reg<'a> = &'a P<Value>;
pub type Mem<'a> = &'a P<Value>;
// X86_64
#[cfg(target_arch = "x86_64")]
......@@ -24,6 +27,8 @@ pub mod x86_64;
#[cfg(target_arch = "x86_64")]
pub use compiler::backend::x86_64::init_machine_regs_for_func;
#[cfg(target_arch = "x86_64")]
pub use compiler::backend::x86_64::get_color_for_precolroed;
#[cfg(target_arch = "x86_64")]
pub use compiler::backend::x86_64::number_of_regs_in_group;
#[cfg(target_arch = "x86_64")]
......
......@@ -319,7 +319,10 @@ pub fn build_chaitin_briggs (cf: &mut CompiledFunction, func: &MuFunctionVersion
for reg in backend::all_regs().values() {
let reg_id = reg.extract_ssa_id().unwrap();
let node = ig.new_node(reg_id, &func.context);
ig.color_node(node, reg_id);
let precolor = backend::get_color_for_precolroed(reg_id);
ig.color_node(node, precolor);
}
// Initialize and creates nodes for all the involved temps/regs
......@@ -460,141 +463,141 @@ pub fn build_chaitin_briggs (cf: &mut CompiledFunction, func: &MuFunctionVersion
// from tony's code src/RegAlloc/Liveness.java
// this function is no longer used
#[allow(dead_code)]
pub fn build (cf: &CompiledFunction, func: &MuFunctionVersion) -> InterferenceGraph {
let mut ig = InterferenceGraph::new();
// precolor machine register nodes
for reg in backend::all_regs().values() {
let reg_id = reg.extract_ssa_id().unwrap();
let node = ig.new_node(reg_id, &func.context);
ig.color_node(node, reg_id);
}
// Liveness Analysis
let n_insts = cf.mc().number_of_insts();
let mut live_in : Vec<Vec<MuID>> = vec![vec![]; n_insts];
let mut live_out : Vec<Vec<MuID>> = vec![vec![]; n_insts];
let mut work_list : LinkedList<usize> = LinkedList::new();
// Initialize 'in' sets for each node in the flow graph
// and creates nodes for all the involved temps/regs
for i in 0..n_insts {
let ref mut in_set = live_in[i];
for reg_id in cf.mc().get_inst_reg_defines(i) {
ig.new_node(reg_id, &func.context);
}
for reg_id in cf.mc().get_inst_reg_uses(i) {
ig.new_node(reg_id, &func.context);
in_set.push(reg_id);
}
work_list.push_front(i);
}
// all nodes has been added, we init graph (create adjacency matrix)
ig.init_graph();
// compute liveIn and liveOut iteratively
trace!("build live outs");
while !work_list.is_empty() {
let n = work_list.pop_front().unwrap();
trace!("build liveout for #{}", n);
let ref mut out_set = live_out[n];
// out = union(in[succ]) for all succs
for succ in cf.mc().get_succs(n) {
trace!("add successor's livein {:?} to #{}", &live_in[*succ], n);
vec_utils::add_all(out_set, &live_in[*succ]);
}
// in = use(i.e. live_in) + (out - def)
let mut diff = out_set.clone();
for def in cf.mc().get_inst_reg_defines(n) {
vec_utils::remove_value(&mut diff, def);
trace!("removing def: {}", def);
trace!("diff = {:?}", diff);
}
trace!("out - def = {:?}", diff);
if !diff.is_empty() {
let ref mut in_set = live_in[n];
trace!("in = (use) {:?}", in_set);
if vec_utils::add_all(in_set, &diff) {
for p in cf.mc().get_preds(n) {
work_list.push_front(*p);
}
}
}
trace!("in = use + (out - def) = {:?}", live_in[n]);
}
// debug live-outs
if cfg!(debug_assertions) {
trace!("check live-outs");
for n in 0..n_insts {
let ref mut live = live_out[n];
trace!("#{}\t{:?}", n, live);
}
}
// build interference graph
for n in 0..n_insts {
let ref mut live = live_out[n];
let src : Option<MuID> = {
if cf.mc().is_move(n) {
let src = cf.mc().get_inst_reg_uses(n);
let dst = cf.mc().get_inst_reg_defines(n);
// src may be an immediate number
// but dest is definitly a register
debug_assert!(dst.len() == 1);
if src.len() == 1 {
let node1 = ig.get_node(src[0]);
let node2 = ig.get_node(dst[0]);
ig.add_move(node1, node2);
Some(src[0])
} else {
None
}
} else {
None
}
};
for d in cf.mc().get_inst_reg_defines(n) {
for t in live.iter() {
if src.is_none() || (src.is_some() && *t != src.unwrap()) {
let from = ig.get_node(d);
let to = ig.get_node(*t);
if !ig.is_same_node(from, to) && !ig.is_adj(from, to) {
if !ig.is_colored(from) {
ig.add_interference_edge(from, to);
}
if !ig.is_colored(to) {
ig.add_interference_edge(to, from);
}
}
}
}
}
for d in cf.mc().get_inst_reg_defines(n) {
vec_utils::remove_value(live, d);
}
for u in cf.mc().get_inst_reg_uses(n) {
live.push(u);
}
}
ig
}
//#[allow(dead_code)]
//pub fn build (cf: &CompiledFunction, func: &MuFunctionVersion) -> InterferenceGraph {
// let mut ig = InterferenceGraph::new();
//
// // precolor machine register nodes
// for reg in backend::all_regs().values() {
// let reg_id = reg.extract_ssa_id().unwrap();
// let node = ig.new_node(reg_id, &func.context);
// ig.color_node(node, reg_id);
// }
//
// // Liveness Analysis
// let n_insts = cf.mc().number_of_insts();
// let mut live_in : Vec<Vec<MuID>> = vec![vec![]; n_insts];
// let mut live_out : Vec<Vec<MuID>> = vec![vec![]; n_insts];
// let mut work_list : LinkedList<usize> = LinkedList::new();
//
// // Initialize 'in' sets for each node in the flow graph
// // and creates nodes for all the involved temps/regs
// for i in 0..n_insts {
// let ref mut in_set = live_in[i];
//
// for reg_id in cf.mc().get_inst_reg_defines(i) {
// ig.new_node(reg_id, &func.context);
// }
//
// for reg_id in cf.mc().get_inst_reg_uses(i) {
// ig.new_node(reg_id, &func.context);
//
// in_set.push(reg_id);
// }
//
// work_list.push_front(i);
// }
//
// // all nodes has been added, we init graph (create adjacency matrix)
// ig.init_graph();
//
// // compute liveIn and liveOut iteratively
// trace!("build live outs");
// while !work_list.is_empty() {
// let n = work_list.pop_front().unwrap();
// trace!("build liveout for #{}", n);
// let ref mut out_set = live_out[n];
//
// // out = union(in[succ]) for all succs
// for succ in cf.mc().get_succs(n) {
// trace!("add successor's livein {:?} to #{}", &live_in[*succ], n);
// vec_utils::add_all(out_set, &live_in[*succ]);
// }
//
// // in = use(i.e. live_in) + (out - def)
// let mut diff = out_set.clone();
// for def in cf.mc().get_inst_reg_defines(n) {
// vec_utils::remove_value(&mut diff, def);
// trace!("removing def: {}", def);
// trace!("diff = {:?}", diff);
// }
// trace!("out - def = {:?}", diff);
//
// if !diff.is_empty() {
// let ref mut in_set = live_in[n];
// trace!("in = (use) {:?}", in_set);
//
// if vec_utils::add_all(in_set, &diff) {
// for p in cf.mc().get_preds(n) {
// work_list.push_front(*p);
// }
// }
// }
// trace!("in = use + (out - def) = {:?}", live_in[n]);
// }
//
// // debug live-outs
// if cfg!(debug_assertions) {
// trace!("check live-outs");
// for n in 0..n_insts {
// let ref mut live = live_out[n];
// trace!("#{}\t{:?}", n, live);
// }
// }
//
// // build interference graph
// for n in 0..n_insts {
// let ref mut live = live_out[n];
//
// let src : Option<MuID> = {
// if cf.mc().is_move(n) {
// let src = cf.mc().get_inst_reg_uses(n);
// let dst = cf.mc().get_inst_reg_defines(n);
//
// // src may be an immediate number
// // but dest is definitly a register
// debug_assert!(dst.len() == 1);
//
// if src.len() == 1 {
// let node1 = ig.get_node(src[0]);
// let node2 = ig.get_node(dst[0]);
// ig.add_move(node1, node2);
//
// Some(src[0])
// } else {
// None
// }
// } else {
// None
// }
// };
//
// for d in cf.mc().get_inst_reg_defines(n) {
// for t in live.iter() {
// if src.is_none() || (src.is_some() && *t != src.unwrap()) {
// let from = ig.get_node(d);
// let to = ig.get_node(*t);
//
// if !ig.is_same_node(from, to) && !ig.is_adj(from, to) {
// if !ig.is_colored(from) {
// ig.add_interference_edge(from, to);
// }
// if !ig.is_colored(to) {
// ig.add_interference_edge(to, from);
// }
// }
// }
// }
// }
//
// for d in cf.mc().get_inst_reg_defines(n) {
// vec_utils::remove_value(live, d);
// }
//
// for u in cf.mc().get_inst_reg_uses(n) {
// live.push(u);
// }
// }
//
// ig
//}
......@@ -330,7 +330,7 @@ fn test_sgt_value() {
let lib = testutil::compile_fnc("sgt_value", &sgt_value);
unsafe {
let sgt_value : libloading::Symbol<unsafe extern fn(i64, i64) -> u64> = lib.get(b"sgt_value").unwrap();
let sgt_value : libloading::Symbol<unsafe extern fn(i64, i64) -> u8> = lib.get(b"sgt_value").unwrap();
let res = sgt_value(255, 0);
println!("sgt_value(255, 0) = {}", res);
......@@ -386,7 +386,7 @@ fn test_sgt_u8_value() {
let lib = testutil::compile_fnc("sgt_u8_value", &sgt_u8_value);
unsafe {
let sgt_u8_value : libloading::Symbol<unsafe extern fn(i8, i8) -> u64> = lib.get(b"sgt_u8_value").unwrap();
let sgt_u8_value : libloading::Symbol<unsafe extern fn(i8, i8) -> u8> = lib.get(b"sgt_u8_value").unwrap();
let res = sgt_u8_value(-1, 0);
println!("sgt_u8_value(-1, 0) = {}", res);
......
......@@ -15,7 +15,7 @@ fn test_add_u8() {
let lib = testutil::compile_fnc("add_u8", &add_u8);
unsafe {
let add_u8 : libloading::Symbol<unsafe extern fn(u8, u8) -> u64> = lib.get(b"add_u8").unwrap();
let add_u8 : libloading::Symbol<unsafe extern fn(u8, u8) -> u8> = lib.get(b"add_u8").unwrap();
let add_u8_1_1 = add_u8(1, 1);
println!("add_u8(1, 1) = {}", add_u8_1_1);
......@@ -99,7 +99,7 @@ fn test_truncate() {
let lib = testutil::compile_fnc("truncate", &truncate);
unsafe {
let truncate : libloading::Symbol<unsafe extern fn(u64) -> u64> = lib.get(b"truncate").unwrap();
let truncate : libloading::Symbol<unsafe extern fn(u64) -> u8> = lib.get(b"truncate").unwrap();
let res = truncate(0xF01u64);
println!("truncate(0xF01) = {}", res);
......
......@@ -101,8 +101,8 @@ fn test_type_constructors() {
assert_type!(*types[12], "stackref");
assert_type!(*types[13], "tagref64");
assert_type!(*types[14], "vector<int<8> 5>");
assert_type!(*types[15], "funcref<[void] -> [int<8>, int<8>]>");
assert_type!(*types[16], "ufuncref<[void] -> [int<8>, int<8>]>");
assert_type!(*types[15], "funcref<[int<8>, int<8>] -> [void]>");
assert_type!(*types[16], "ufuncref<[int<8>, int<8>] -> [void]>");
}
#[test]
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment