Commit 81a4c700 authored by qinsoon's avatar qinsoon

put floatingpoint constant to memory

parent 98fee628
......@@ -26,4 +26,5 @@ lazy_static = "*"
log = "*"
simple_logger = "*"
rodal = { git = "https://gitlab.anu.edu.au/mu/rodal", version = ">= 0.0.5" }
regex = "*"
#rodal = { path = "../../../rodal_test/rodal", version = ">= 0.0.5" }
......@@ -1486,7 +1486,8 @@ pub fn mangle_name(name: MuName) -> MuName {
"__mu_".to_string() + name.as_str()
}
// WARNING: This only reverses mangle_name above when no warning is issued)
/// demangles a Mu name
// WARNING: This only reverses mangle_name above when no warning is issued)
pub fn demangle_name(mut name: MuName) -> MuName {
let name = if cfg!(target_os = "macos") && name.starts_with("___mu_") {
name.split_off(1)
......@@ -1509,57 +1510,28 @@ pub fn demangle_name(mut name: MuName) -> MuName {
name
}
// TODO: Why the hell isn't this working?
pub fn demangle_text(text: String) -> String {
let text = text.as_bytes();
let n = text.len();
let mut output = String::new();
extern crate regex;
// We have a mangled name
let mut last_i = 0; // The last i value that we dumped to output
let mut i = 0;
// TODO: this should work for utf-8 stuff right? (sinces all mangled names are in ascii)
while i < n {
let c = text[i] as char;
// We're at the beginining of the string
// wait for a word boundry
if c.is_alphanumeric() || c == '_' {
// We just found a mangled name
if text[i..].starts_with("__mu_".as_bytes()) {
output += std::str::from_utf8(&text[last_i..i]).unwrap();
let start = i;
// Find the end of the name
while i < n {
let c = text[i] as char;
if !c.is_alphanumeric() && c != '_' {
break; // We found the end!
}
i += 1;
}
/// identifies mu names and demangles them
pub fn demangle_text(text: String) -> String {
use self::regex::Regex;
output +=
demangle_name(String::from_utf8(text[start..i].to_vec()).unwrap()).as_str();
// Skip to the end of the name
last_i = i;
continue;
} else {
// Skip to the end of this alphanumeric sequence
while i < n {
let c = text[i] as char;
if !c.is_alphanumeric() && c != '_' {
break; // We found the end!
}
i += 1;
}
}
lazy_static!{
static ref IDENT_NAME: Regex = if cfg!(target_os = "macos") {
Regex::new(r"___mu_\w+").unwrap()
} else {
Regex::new(r"__mu_\w+").unwrap()
};
}
continue;
}
// Not the start of mangled name, continue
i += 1;
let mut res = text.clone();
for cap in IDENT_NAME.captures_iter(&text) {
let name = cap.get(0).unwrap().as_str().to_string();
let demangled = demangle_name(name.clone());
res = res.replacen(&name, &demangled, 1);
}
// Return output plus whatever is left of the string
output + std::str::from_utf8(&text[last_i..n]).unwrap()
res
}
......
......@@ -33,6 +33,8 @@
#[macro_use]
extern crate rodal;
#[macro_use]
extern crate log;
extern crate simple_logger;
#[macro_use]
extern crate lazy_static;
......
......@@ -3747,8 +3747,6 @@ pub fn emit_code(fv: &mut MuFunctionVersion, vm: &VM) {
// constants in text section
file.write("\t.text\n".as_bytes()).unwrap();
// alignment for constant are 16 bytes
write_const_align(&mut file);
// write constants
for (id, constant) in cf.consts.iter() {
let mem = cf.const_mem.get(id).unwrap();
......@@ -3768,6 +3766,7 @@ pub fn emit_code(fv: &mut MuFunctionVersion, vm: &VM) {
Ok(_) => info!("emit code to {}", file_path.to_str().unwrap())
}
}
info!("write demangled code...");
// Read the file we just wrote above an demangle it
{
let mut demangled_path = path::PathBuf::new();
......@@ -3827,11 +3826,6 @@ fn check_align(align: ByteSize) -> ByteSize {
}
}
/// writes constant alignmnet (16 bytes)
fn write_const_align(f: &mut File) {
write_align(f, MAX_ALIGN);
}
/// writes alignment in bytes for linux
#[cfg(not(feature = "sel4-rumprun"))]
#[cfg(target_os = "linux")]
......@@ -3881,6 +3875,7 @@ fn write_const(f: &mut File, constant: P<Value>, loc: P<Value>) {
)
}
};
write_align(f, MAX_ALIGN);
writeln!(f, "{}:", symbol(mangle_name(label))).unwrap();
// actual value
......@@ -3930,16 +3925,14 @@ fn write_const_value(f: &mut File, constant: P<Value>) {
.unwrap();
}
&Constant::Float(val) => {
let bytes: [u8; 4] = unsafe { mem::transmute(val) };
f.write("\t.long ".as_bytes()).unwrap();
f.write(&bytes).unwrap();
f.write("\n".as_bytes()).unwrap();
use utils::mem::f32_to_raw;
f.write_fmt(format_args!("\t.long {}\n", f32_to_raw(val) as u32))
.unwrap();
}
&Constant::Double(val) => {
let bytes: [u8; 8] = unsafe { mem::transmute(val) };
f.write("\t.quad ".as_bytes()).unwrap();
f.write(&bytes).unwrap();
f.write("\n".as_bytes()).unwrap();
use utils::mem::f64_to_raw;
f.write_fmt(format_args!("\t.quad {}\n", f64_to_raw(val) as u64))
.unwrap();
}
&Constant::NullRef => f.write_fmt(format_args!("\t.quad 0\n")).unwrap(),
&Constant::ExternSym(ref name) => f.write_fmt(format_args!("\t.quad {}\n", name)).unwrap(),
......
......@@ -1018,14 +1018,12 @@ impl<'a> InstructionSelection {
// punpckldq UITOFP_C0, tmp_res -> tmp_res
// (interleaving low bytes:
// xmm = xmm[0] mem[0] xmm[1] mem[1])
let mem_c0 =
self.get_mem_for_const(UITOFP_C0.clone(), vm);
let mem_c0 = self.get_mem_for_const(&UITOFP_C0, vm);
self.backend
.emit_punpckldq_f64_mem128(&tmp_res, &mem_c0);
// subpd UITOFP_C1, tmp_res -> tmp_res
let mem_c1 =
self.get_mem_for_const(UITOFP_C1.clone(), vm);
let mem_c1 = self.get_mem_for_const(&UITOFP_C1, vm);
self.backend
.emit_subpd_f64_mem128(&tmp_res, &mem_c1);
......@@ -1206,7 +1204,7 @@ impl<'a> InstructionSelection {
// movsd FPTOUI_C_DOUBLE -> %tmp1
let mem_c =
self.get_mem_for_const(FPTOUI_C_DOUBLE.clone(), vm);
self.get_mem_for_const(&FPTOUI_C_DOUBLE, vm);
self.backend.emit_movsd_f64_mem64(&tmp1, &mem_c);
// movapd %tmp_op -> %tmp2
......@@ -1276,8 +1274,7 @@ impl<'a> InstructionSelection {
);
// movss FPTOUI_C_FLOAT -> %tmp1
let mem_c =
self.get_mem_for_const(FPTOUI_C_FLOAT.clone(), vm);
let mem_c = self.get_mem_for_const(&FPTOUI_C_FLOAT, vm);
self.backend.emit_movss_f32_mem32(&tmp1, &mem_c);
// movaps %tmp_op -> %tmp2
......@@ -3995,7 +3992,7 @@ impl<'a> InstructionSelection {
if x86_64::is_valid_x86_imm(arg) {
self.backend.emit_mov_r_imm(reg, int_const as i32);
} else {
// FIXME: put the constant to memory
assert!(reg.ty.get_int_length().unwrap() == 64);
self.backend.emit_mov_r64_imm64(reg, int_const as i64);
}
} else {
......@@ -4623,7 +4620,7 @@ impl<'a> InstructionSelection {
let arg_tys = arg_values.iter().map(|x| x.ty.clone()).collect();
let callconv = swapstack::compute_arguments(&arg_tys);
// store stack arguments first - as we may kill our own stack soon
// pass stack arguments
let mut stack_args = vec![];
for i in 0..callconv.len() {
let ref cc = callconv[i];
......@@ -4660,6 +4657,7 @@ impl<'a> InstructionSelection {
vm
);
// restore first GPR
self.backend.emit_pop_r64(&x86_64::RDI);
}
......@@ -5458,39 +5456,16 @@ impl<'a> InstructionSelection {
TreeNode_::Value(ref pv) => {
match pv.v {
Value_::SSAVar(_) => pv.clone(),
Value_::Constant(Constant::Double(val)) => {
use std::mem;
// val into u64
let val_u64: u64 = unsafe { mem::transmute(val) };
// mov val_u64 -> tmp_int
let tmp_int = self.make_temporary(f_context, UINT64_TYPE.clone(), vm);
self.backend.emit_mov_r64_imm64(&tmp_int, val_u64 as i64);
// movq tmp_int -> tmp_fp
Value_::Constant(Constant::Double(_)) => {
let mem = self.get_mem_for_const(pv, vm);
let tmp_fp = self.make_temporary(f_context, DOUBLE_TYPE.clone(), vm);
self.backend.emit_mov_fpr_r64(&tmp_fp, &tmp_int);
self.backend.emit_movsd_f64_mem64(&tmp_fp, &mem);
tmp_fp
}
Value_::Constant(Constant::Float(val)) => {
use std::mem;
// val into u32
let val_u32: u32 = unsafe { mem::transmute(val) };
// mov val_u32 -> tmp_int
let tmp_int = self.make_temporary(f_context, UINT32_TYPE.clone(), vm);
self.backend.emit_mov_r_imm(&tmp_int, val_u32 as i32);
// movq tmp_int (64) -> tmp_fp
Value_::Constant(Constant::Float(_)) => {
let mem = self.get_mem_for_const(pv, vm);
let tmp_fp = self.make_temporary(f_context, FLOAT_TYPE.clone(), vm);
self.backend.emit_mov_fpr_r64(
&tmp_fp,
unsafe { &tmp_int.as_type(UINT64_TYPE.clone()) }
);
self.backend.emit_movss_f32_mem32(&tmp_fp, &mem);
tmp_fp
}
_ => panic!("expected fpreg")
......@@ -6408,13 +6383,13 @@ impl<'a> InstructionSelection {
}
/// puts a constant in memory, and returns its memory location P<Value>
fn get_mem_for_const(&mut self, val: P<Value>, vm: &VM) -> P<Value> {
fn get_mem_for_const(&mut self, val: &P<Value>, vm: &VM) -> P<Value> {
let id = val.id();
if self.current_constants_locs.contains_key(&id) {
self.current_constants_locs.get(&id).unwrap().clone()
} else {
let const_value_loc = vm.allocate_const(val.clone());
let const_value_loc = vm.allocate_const(val);
let const_mem_val = match const_value_loc {
ValueLocation::Relocatable(_, ref name) => {
P(Value {
......
......@@ -196,13 +196,13 @@ impl ValueLocation {
pub fn from_constant(c: Constant) -> ValueLocation {
match c {
Constant::Int(int_val) => {
ValueLocation::Constant(RegGroup::GPR, utils::mem::u64_to_raw(int_val))
ValueLocation::Constant(RegGroup::GPR, utils::mem::u64_to_raw(int_val) as Word)
}
Constant::Float(f32_val) => {
ValueLocation::Constant(RegGroup::FPR, utils::mem::f32_to_raw(f32_val))
ValueLocation::Constant(RegGroup::FPR, utils::mem::f32_to_raw(f32_val) as Word)
}
Constant::Double(f64_val) => {
ValueLocation::Constant(RegGroup::FPR, utils::mem::f64_to_raw(f64_val))
ValueLocation::Constant(RegGroup::FPR, utils::mem::f64_to_raw(f64_val) as Word)
}
_ => unimplemented!()
}
......
......@@ -17,38 +17,31 @@ pub extern crate memmap;
/// secured memory operations: memset, memzero, etc.
pub extern crate memsec;
use Word;
#[allow(unused_imports)] // import both endianness (we may not use big endian though)
use byteorder::{LittleEndian, BigEndian, ReadBytesExt, WriteBytesExt, ByteOrder};
/// returns bit representations for u64
#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
pub fn u64_to_raw(val: u64) -> Word {
pub fn u64_to_raw(val: u64) -> u64 {
let mut ret = vec![];
ret.write_u64::<LittleEndian>(val).unwrap();
as_word(ret)
LittleEndian::read_uint(&mut ret, 8)
}
/// returns bit representations for f32
#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
pub fn f32_to_raw(val: f32) -> Word {
pub fn f32_to_raw(val: f32) -> u32 {
let mut ret = vec![];
ret.write_f32::<LittleEndian>(val).unwrap();
as_word(ret)
LittleEndian::read_uint(&mut ret, 4) as u32
}
/// returns bit representations for f64
#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
pub fn f64_to_raw(val: f64) -> Word {
pub fn f64_to_raw(val: f64) -> u64 {
let mut ret = vec![];
ret.write_f64::<LittleEndian>(val).unwrap();
as_word(ret)
}
/// returns bit representations for Vec<u8>
#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
pub fn as_word(mut u8_array: Vec<u8>) -> Word {
LittleEndian::read_uint(&mut u8_array, 8) as Word
LittleEndian::read_uint(&mut ret, 8)
}
#[cfg(test)]
......
......@@ -557,7 +557,7 @@ impl<'a> VM {
/// allocates memory for a constant that needs to be put in memory
/// For AOT, we simply create a label for it, and let code emitter allocate the memory
#[cfg(feature = "aot")]
pub fn allocate_const(&self, val: P<Value>) -> ValueLocation {
pub fn allocate_const(&self, val: &P<Value>) -> ValueLocation {
let id = val.id();
let name = format!("CONST_{}_{}", id, val.name());
......
......@@ -319,7 +319,7 @@ fn sitofp() -> VM {
}
#[test]
fn test_ui64tofp() {
fn test_ui64tofp_simple() {
build_and_run_test!(ui64tofp, ui64tofp_test1);
build_and_run_test!(ui64tofp, ui64tofp_test2);
}
......
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