To protect your data, the CISO officer has suggested users to enable GitLab 2FA as soon as possible.

Commit 2322717d authored by Isaac Oscar Gariano's avatar Isaac Oscar Gariano
Browse files

Merge branch 'develop' of gitlab.anu.edu.au:mu/mu-impl-fast into develop

parents 9461cf01 97122e24
......@@ -1111,7 +1111,7 @@ impl Clone for MuEntityHeader {
}
pub fn name_check(name: MuName) -> MuName {
let name = name.replace('.', "_");
let name = name.replace('.', "$");
if name.starts_with("@") || name.starts_with("%") {
let (_, name) = name.split_at(1);
......
......@@ -22,6 +22,8 @@
// TODO: Move architecture independent codes in here, inst_sel and asm_backend to somewhere else...
pub mod inst_sel;
use utils::bit_utils::bits_ones;
mod codegen;
pub use compiler::backend::aarch64::codegen::CodeGenerator;
......@@ -1190,12 +1192,6 @@ fn hfa_length(t : P<MuType>) -> usize
}
}
#[inline(always)]
// Returns the number that has 'n' 1's in a row (i.e. 2^n-1)
pub fn bits_ones(n: usize) -> u64 {
if n == 64 { (-(1 as i64)) as u64 }
else { (1 << n) - 1 }
}
// val is an unsigned multiple of n and val/n fits in 12 bits
#[inline(always)]
pub fn is_valid_immediate_offset(val: i64, n : usize) -> bool {
......
......@@ -26,6 +26,20 @@ pub fn lower_bits_u8(value: u8, len: usize) -> u8 {
// u64
#[inline(always)]
// Returns the number that has 'n' 1's in a row (i.e. 2^n-1)
pub fn bits_ones(n: usize) -> u64 {
if n == 64 { (-(1 as i64)) as u64 }
else { (1 << n) - 1 }
}
#[inline(always)]
pub fn u64_asr(val: u64, shift: u32) -> u64 {
let _val: i64 = val as i64;
let res: i64 = _val >> shift;
res as u64
}
#[inline(always)]
pub fn set_nth_bit_u64 (value: u64, index: usize, set_value: u8) -> u64 {
value ^ (((-(set_value as i64) as u64) ^ value) & (1 << index))
......
......@@ -41,6 +41,9 @@ use std::sync::RwLock;
use std::sync::RwLockWriteGuard;
use std::sync::atomic::{AtomicUsize, AtomicBool, ATOMIC_BOOL_INIT, ATOMIC_USIZE_INIT, Ordering};
use std;
use utils::bit_utils::{bits_ones, u64_asr};
// FIXME:
// besides fields in VM, there are some 'globals' we need to persist
// such as STRUCT_TAG_MAP
......@@ -1126,14 +1129,12 @@ impl <'a> VM {
unsafe {
match val.v {
APIHandleValue::Int(ival, bits) => {
let trunc: u64 = ival & bits_ones(bits);
match bits {
1 => addr.store::<u8>((ival as u8) & 0b1u8),
6 => addr.store::<u8>((ival as u8) & 0b111111u8),
8 => addr.store::<u8>(ival as u8),
16 => addr.store::<u16>(ival as u16),
32 => addr.store::<u32>(ival as u32),
52 => addr.store::<u64>(ival & ((1 << 51)-1)),
64 => addr.store::<u64>(ival),
1 ... 8 => addr.store::<u8>(trunc as u8),
9 ... 16 => addr.store::<u16>(trunc as u16),
17 ... 32 => addr.store::<u32>(trunc as u32),
33 ... 64 => addr.store::<u64>(trunc as u64),
_ => panic!("unimplemented int length")
}
},
......@@ -1369,7 +1370,7 @@ impl <'a> VM {
self.new_handle(APIHandle {
id: handle_id,
v : APIHandleValue::Double(
value.v.as_tr64() as f64
unsafe { std::mem::transmute(value.v.as_tr64()) }
)
})
}
......@@ -1396,7 +1397,7 @@ impl <'a> VM {
v : APIHandleValue::Ref(types::REF_VOID_TYPE.clone(),
unsafe { Address::from_usize(
((opnd & 0x7ffffffffff8u64) |
((opnd & 0x8000000000000000u64) >> 16)) as usize
u64_asr((opnd & 0x8000000000000000u64), 16)) as usize
) })
})
}
......@@ -1408,7 +1409,7 @@ impl <'a> VM {
self.new_handle(APIHandle {
id: handle_id,
v : APIHandleValue::Int(
(((opnd & 0x000f800000000000u64) >> 46) | ((opnd & 0x4) >> 2)),
(u64_asr((opnd & 0x000f800000000000u64), 46) | (u64_asr((opnd & 0x4), 2))),
6
)
})
......@@ -1417,7 +1418,7 @@ impl <'a> VM {
// See: `fpToTr64`
pub fn handle_tr64_from_fp(&self, value: APIHandleArg) -> APIHandleResult {
let handle_id = self.next_id();
let double_bits = value.v.as_double() as u64;
let double_bits = unsafe { std::mem::transmute(value.v.as_double()) };
let result_bits = if value.v.as_double().is_nan() {
double_bits & 0xfff8000000000000u64 | 0x0000000000000008u64
......
......@@ -24,6 +24,7 @@ mod ir_macros;
mod test_ir;
mod test_compiler;
mod test_runtime;
mod test_api;
mod common {
use std::fmt;
......
// 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.
mod test_tr64;
......@@ -17,6 +17,9 @@ use mu::vm::handle::*;
use mu::ast::types::*;
use mu::utils::Address;
use std::f64;
use std::mem::transmute;
/**
* Helper functions to test VM:: methods with literal values
*
......@@ -52,11 +55,11 @@ fn int52(val: u64) -> APIHandle {
}
}
fn ref_void(val: usize) -> APIHandle {
fn ref_void(val: u64) -> APIHandle {
APIHandle {
id: 0, // arbitrary
v : APIHandleValue::Ref(REF_VOID_TYPE.clone(),
unsafe { Address::from_usize(val) })
unsafe { Address::from_usize(val as usize) })
}
}
......@@ -78,65 +81,87 @@ fn test_nan_with_suffix_1_is_integer() {
assert!(vm.handle_tr64_is_int(&tr64(0xffffffffffffffffu64)));
}
// FIXME: Convert the rest of these into Rust tests, as above
#[test]
fn test_nan_with_suffix_10_is_ref() {
let vm = VM::new();
/*
it should "treat a NaN with suffix 10 as a double." in {
OpHelper.tr64IsRef(0x7ff0000000000002L) shouldBe true
OpHelper.tr64IsRef(0xfff0000000000002L) shouldBe true
OpHelper.tr64IsRef(0xfffffffffffffffeL) shouldBe true
}
assert!(vm.handle_tr64_is_ref(&tr64(0x7ff0000000000002u64)));
assert!(vm.handle_tr64_is_ref(&tr64(0xfff0000000000002u64)));
assert!(vm.handle_tr64_is_ref(&tr64(0xfffffffffffffffeu64)));
}
it should "treat other bit patterns as double" in {
OpHelper.tr64IsFP(0x0L) shouldBe true
OpHelper.tr64IsFP(0x123456789abcdef0L) shouldBe true
OpHelper.tr64IsFP(0x7ff123456789abccL) shouldBe true
OpHelper.tr64IsFP(0xfffffffffffffffcL) shouldBe true
OpHelper.tr64IsFP(doubleToRawLongBits(3.1415927)) shouldBe true
}
#[test]
fn test_other_bit_pattern_is_double() {
let vm = VM::new();
it should "encode integers" in {
OpHelper.intToTr64(0x0000000000000L) shouldBe 0x7ff0000000000001L
OpHelper.intToTr64(0xfffffffffffffL) shouldBe 0xffffffffffffffffL
OpHelper.intToTr64(0x5555555555555L) shouldBe 0x7ffaaaaaaaaaaaabL
OpHelper.intToTr64(0xaaaaaaaaaaaaaL) shouldBe 0xfff5555555555555L
}
assert!(vm.handle_tr64_is_fp(&tr64(0x0u64)));
assert!(vm.handle_tr64_is_fp(&tr64(0x123456789abcdef0u64)));
assert!(vm.handle_tr64_is_fp(&tr64(0x7ff123456789abccu64)));
assert!(vm.handle_tr64_is_fp(&tr64(0xfffffffffffffffcu64)));
unsafe { assert!(vm.handle_tr64_is_fp(&tr64(transmute(3.1415927f64)))); }
}
it should "encode double" in {
OpHelper.fpToTr64(3.14) shouldBe java.lang.Double.doubleToRawLongBits(3.14)
OpHelper.fpToTr64(-3.14) shouldBe java.lang.Double.doubleToRawLongBits(-3.14)
OpHelper.fpToTr64(java.lang.Double.POSITIVE_INFINITY) shouldBe 0x7ff0000000000000L
OpHelper.fpToTr64(longBitsToDouble(0x7ff123456789abcdL)) shouldBe 0x7ff0000000000008L
isNaN(longBitsToDouble(OpHelper.fpToTr64(longBitsToDouble(0x7ff123456789abcdL)))) shouldBe true
}
#[test]
fn test_encode_int() {
let vm = VM::new();
it should "encode ref and tag" in {
OpHelper.refToTr64(0x000000000000L, 0x00L) shouldBe 0x7ff0000000000002L
OpHelper.refToTr64(0x7ffffffffff8L, 0x00L) shouldBe 0x7ff07ffffffffffaL
OpHelper.refToTr64(0xfffffffffffffff8L, 0x00L) shouldBe 0xfff07ffffffffffaL
OpHelper.refToTr64(0x000000000000L, 0x3fL) shouldBe 0x7fff800000000006L
}
assert_eq!(vm.handle_tr64_from_int(&int52(0x0000000000000u64)).v.as_tr64(), 0x7ff0000000000001u64);
assert_eq!(vm.handle_tr64_from_int(&int52(0xfffffffffffffu64)).v.as_tr64(), 0xffffffffffffffffu64);
assert_eq!(vm.handle_tr64_from_int(&int52(0x5555555555555u64)).v.as_tr64(), 0x7ffaaaaaaaaaaaabu64);
assert_eq!(vm.handle_tr64_from_int(&int52(0xaaaaaaaaaaaaau64)).v.as_tr64(), 0xfff5555555555555u64);
}
it should "decode integer" in {
OpHelper.tr64ToInt(0x7ff0000000000001L) shouldBe 0
OpHelper.tr64ToInt(0xfff0000000000001L) shouldBe 0x8000000000000L
OpHelper.tr64ToInt(0xfff5555555555555L) shouldBe 0xaaaaaaaaaaaaaL
OpHelper.tr64ToInt(0x7ffaaaaaaaaaaaabL) shouldBe 0x5555555555555L
}
#[test]
fn test_encode_double() {
let vm = VM::new();
it should "decode double" in {
OpHelper.tr64ToFP(0x0000000000000000L) shouldBe +0.0
OpHelper.tr64ToFP(0x8000000000000000L) shouldBe -0.0
OpHelper.tr64ToFP(0x3ff0000000000000L) shouldBe 1.0
isNaN(OpHelper.tr64ToFP(0x7ff0000000000008L)) shouldBe true
unsafe {
assert_eq!(vm.handle_tr64_from_fp(&double(3.14_f64)).v.as_tr64(), transmute(3.14_f64));
assert_eq!(vm.handle_tr64_from_fp(&double(-3.14_f64)).v.as_tr64(), transmute(-3.14_f64));
assert_eq!(vm.handle_tr64_from_fp(&double(f64::INFINITY)).v.as_tr64(), 0x7ff0000000000000u64);
assert_eq!(vm.handle_tr64_from_fp(&double(transmute(0x7ff123456789abcdu64))).v.as_tr64(), 0x7ff0000000000008u64);
assert!(transmute::<u64, f64>((vm.handle_tr64_from_fp(&double(transmute(0x7ff123456789abcdu64))).v.as_tr64())).is_nan());
}
}
it should "decodde ref and tag" in {
OpHelper.tr64ToRef(0x7ff0555555555552L) shouldBe 0x555555555550L
OpHelper.tr64ToRef(0xfff02aaaaaaaaaaaL) shouldBe 0xffffaaaaaaaaaaa8L
OpHelper.tr64ToTag(0x7ff0555555555552L) shouldBe 0
OpHelper.tr64ToTag(0x7fff800000000006L) shouldBe 0x3f
OpHelper.tr64ToTag(0x7ffa800000000002L) shouldBe 0x2a
OpHelper.tr64ToTag(0x7ff5000000000006L) shouldBe 0x15
}
*/
#[test]
fn test_encode_tagref() {
let vm = VM::new();
assert_eq!(vm.handle_tr64_from_ref(&ref_void(0x000000000000u64), &tag(0x00u64)).v.as_tr64(), 0x7ff0000000000002u64);
assert_eq!(vm.handle_tr64_from_ref(&ref_void(0x7ffffffffff8u64), &tag(0x00u64)).v.as_tr64(), 0x7ff07ffffffffffau64);
assert_eq!(vm.handle_tr64_from_ref(&ref_void(0xfffffffffffffff8u64), &tag(0x00u64)).v.as_tr64(), 0xfff07ffffffffffau64);
assert_eq!(vm.handle_tr64_from_ref(&ref_void(0x000000000000u64), &tag(0x3fu64)).v.as_tr64(), 0x7fff800000000006u64);
}
#[test]
fn test_decode_integer() {
let vm = VM::new();
assert_eq!(vm.handle_tr64_to_int(&tr64(0x7ff0000000000001u64)).v.as_int(), 0u64);
assert_eq!(vm.handle_tr64_to_int(&tr64(0xfff0000000000001u64)).v.as_int(), 0x8000000000000u64);
assert_eq!(vm.handle_tr64_to_int(&tr64(0xfff5555555555555u64)).v.as_int(), 0xaaaaaaaaaaaaau64);
assert_eq!(vm.handle_tr64_to_int(&tr64(0x7ffaaaaaaaaaaaabu64)).v.as_int(), 0x5555555555555u64);
}
#[test]
fn test_decode_double() {
let vm = VM::new();
assert_eq!(vm.handle_tr64_to_fp(&tr64(0x0000000000000000u64)).v.as_double(), 0.0_f64);
assert_eq!(vm.handle_tr64_to_fp(&tr64(0x8000000000000000u64)).v.as_double(), -0.0_f64);
assert_eq!(vm.handle_tr64_to_fp(&tr64(0x3ff0000000000000u64)).v.as_double(), 1.0_f64);
assert!(vm.handle_tr64_to_fp(&tr64(0x7ff0000000000008)).v.as_double().is_nan());
}
#[test]
fn test_decode_tagref() {
let vm = VM::new();
assert_eq!(vm.handle_tr64_to_ref(&tr64(0x7ff0555555555552u64)).v.as_ref().1.as_usize() as u64, 0x555555555550u64);
assert_eq!(vm.handle_tr64_to_ref(&tr64(0xfff02aaaaaaaaaaau64)).v.as_ref().1.as_usize() as u64, 0xffffaaaaaaaaaaa8u64);
assert_eq!(vm.handle_tr64_to_tag(&tr64(0x7ff0555555555552u64)).v.as_int(), 0u64);
assert_eq!(vm.handle_tr64_to_tag(&tr64(0x7fff800000000006u64)).v.as_int(), 0x3fu64);
assert_eq!(vm.handle_tr64_to_tag(&tr64(0x7ffa800000000002u64)).v.as_int(), 0x2au64);
assert_eq!(vm.handle_tr64_to_tag(&tr64(0x7ff5000000000006u64)).v.as_int(), 0x15u64);
}
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