Improve word impls

next
Sayan Nandan 1 year ago
parent 329ef1a27e
commit 4eb2851cf9
No known key found for this signature in database
GPG Key ID: 42EEDF4AE9D96B54

@ -35,7 +35,7 @@ use {
tag::{DataTag, TagUnique},
},
idx::meta::Comparable,
mem::{self, NativeDword, SystemDword},
mem::{self, DwordQN, SpecialPaddedWord, WordIO},
},
core::{
fmt,
@ -47,12 +47,12 @@ use {
pub struct PrimaryIndexKey {
tag: TagUnique,
data: NativeDword,
data: SpecialPaddedWord,
}
impl PrimaryIndexKey {
pub unsafe fn read_uint(&self) -> u64 {
self.data.load_qw()
self.data.load()
}
pub fn uint(&self) -> Option<u64> {
(self.tag == TagUnique::UnsignedInt).then_some(unsafe {
@ -61,7 +61,7 @@ impl PrimaryIndexKey {
})
}
pub unsafe fn read_sint(&self) -> i64 {
self.data.load_qw() as _
self.data.load()
}
pub fn sint(&self) -> Option<i64> {
(self.tag == TagUnique::SignedInt).then_some(unsafe {
@ -105,16 +105,16 @@ impl PrimaryIndexKey {
debug_assert!(Self::check(&dc));
let tag = dc.tag().tag_unique();
let dc = ManuallyDrop::new(dc);
let dword = unsafe {
let (a, b) = unsafe {
// UNSAFE(@ohsayan): this doesn't do anything "bad" by itself. needs the construction to be broken for it to do something silly
dc.as_raw()
}
.load_double();
.dwordqn_load_qw_nw();
Self {
tag,
data: unsafe {
// UNSAFE(@ohsayan): Perfectly safe since we're tranforming it and THIS will not by itself crash anything
core::mem::transmute(dword)
// UNSAFE(@ohsayan): loaded above, writing here
SpecialPaddedWord::new(a, b)
},
}
}
@ -126,12 +126,12 @@ impl PrimaryIndexKey {
}
/// ## Safety
/// If you mess up construction, everything will fall apart
pub unsafe fn new(tag: TagUnique, data: NativeDword) -> Self {
pub unsafe fn new(tag: TagUnique, data: SpecialPaddedWord) -> Self {
Self { tag, data }
}
fn __compute_vdata_offset(&self) -> [usize; 2] {
let [len, data] = self.data.load_double();
let actual_len = len * (self.tag >= TagUnique::Bin) as usize;
let (len, data) = self.data.dwordqn_load_qw_nw();
let actual_len = (len as usize) * (self.tag >= TagUnique::Bin) as usize;
[data, actual_len]
}
fn virtual_block(&self) -> &[u8] {
@ -164,7 +164,7 @@ impl Drop for PrimaryIndexKey {
impl PartialEq for PrimaryIndexKey {
fn eq(&self, other: &Self) -> bool {
let [data_1, data_2] = [self.data.load_double()[0], other.data.load_double()[0]];
let [data_1, data_2]: [u64; 2] = [self.data.load(), other.data.load()];
((self.tag == other.tag) & (data_1 == data_2))
&& self.virtual_block() == other.virtual_block()
}
@ -282,6 +282,8 @@ fn check_pk_extremes() {
let d1 = PrimaryIndexKey::try_from_dc(Datacell::new_uint(u64::MAX)).unwrap();
let d2 = PrimaryIndexKey::try_from_dc(Datacell::from(LitIR::UnsignedInt(u64::MAX))).unwrap();
assert_eq!(d1, d2);
assert_eq!(d1.uint().unwrap(), u64::MAX);
assert_eq!(d2.uint().unwrap(), u64::MAX);
assert_eq!(
test_utils::hash_rs(&state, &d1),
test_utils::hash_rs(&state, &d2)

@ -32,7 +32,7 @@ use {
spec::{Dataspec1D, DataspecMeta1D},
tag::{CUTag, DataTag, TagClass},
},
mem::{NativeQword, SystemDword, SystemTword, WordRW},
mem::{DwordNN, DwordQN, NativeQword, WordIO},
},
core::{fmt, mem, mem::ManuallyDrop, slice, str},
parking_lot::RwLock,
@ -49,7 +49,7 @@ impl Datacell {
pub fn new_bool(b: bool) -> Self {
unsafe {
// UNSAFE(@ohsayan): Correct because we are initializing Self with the correct tag
Self::new(CUTag::BOOL, DataRaw::word(SystemDword::store(b)))
Self::new(CUTag::BOOL, DataRaw::word(WordIO::store(b)))
}
}
pub unsafe fn read_bool(&self) -> bool {
@ -68,7 +68,7 @@ impl Datacell {
pub fn new_uint(u: u64) -> Self {
unsafe {
// UNSAFE(@ohsayan): Correct because we are initializing Self with the correct tag
Self::new(CUTag::UINT, DataRaw::word(SystemDword::store(u)))
Self::new(CUTag::UINT, DataRaw::word(WordIO::store(u)))
}
}
pub unsafe fn read_uint(&self) -> u64 {
@ -87,7 +87,7 @@ impl Datacell {
pub fn new_sint(u: i64) -> Self {
unsafe {
// UNSAFE(@ohsayan): Correct because we are initializing Self with the correct tag
Self::new(CUTag::SINT, DataRaw::word(SystemDword::store(u)))
Self::new(CUTag::SINT, DataRaw::word(WordIO::store(u)))
}
}
pub unsafe fn read_sint(&self) -> i64 {
@ -106,7 +106,7 @@ impl Datacell {
pub fn new_float(f: f64) -> Self {
unsafe {
// UNSAFE(@ohsayan): Correct because we are initializing Self with the correct tag
Self::new(CUTag::FLOAT, DataRaw::word(SystemDword::store(f)))
Self::new(CUTag::FLOAT, DataRaw::word(WordIO::store(f)))
}
}
pub unsafe fn read_float(&self) -> f64 {
@ -128,7 +128,7 @@ impl Datacell {
// UNSAFE(@ohsayan): Correct because we are initializing Self with the correct tag
Self::new(
CUTag::BIN,
DataRaw::word(SystemDword::store((md.len(), md.as_mut_ptr()))),
DataRaw::word(WordIO::store((md.len(), md.as_mut_ptr()))),
)
}
}
@ -152,7 +152,7 @@ impl Datacell {
// UNSAFE(@ohsayan): Correct because we are initializing Self with the correct tag
Self::new(
CUTag::STR,
DataRaw::word(SystemDword::store((md.len(), md.as_mut_ptr()))),
DataRaw::word(WordIO::store((md.len(), md.as_mut_ptr()))),
)
}
}
@ -213,12 +213,10 @@ impl<'a> From<LitIR<'a>> for Datacell {
match l.kind().tag_class() {
tag if tag < TagClass::Bin => unsafe {
// UNSAFE(@ohsayan): Correct because we are using the same tag, and in this case the type doesn't need any advanced construction
let data = l.data().load_qw();
let ptr = l.data().load_double()[1];
Datacell::new(
CUTag::from(l.kind()),
// DO NOT RELY ON the payload's bit pattern; it's padded
DataRaw::word(SystemTword::store_qw_nw(data, ptr as usize)),
DataRaw::word(l.data().dword_promote()),
)
},
TagClass::Bin | TagClass::Str => unsafe {
@ -226,7 +224,7 @@ impl<'a> From<LitIR<'a>> for Datacell {
let mut bin = ManuallyDrop::new(l.read_bin_uck().to_owned().into_boxed_slice());
Datacell::new(
CUTag::from(l.kind()),
DataRaw::word(SystemDword::store((bin.len(), bin.as_mut_ptr()))),
DataRaw::word(WordIO::store((bin.len(), bin.as_mut_ptr()))),
)
},
_ => unsafe {
@ -270,7 +268,11 @@ impl Datacell {
pub fn null() -> Self {
unsafe {
// UNSAFE(@ohsayan): This is a hack. It's safe because we set init to false
Self::_new(CUTag::BOOL, DataRaw::word(NativeQword::store_qw(0)), false)
Self::_new(
CUTag::BOOL,
DataRaw::word(NativeQword::dwordnn_store_qw(0)),
false,
)
}
}
pub fn is_null(&self) -> bool {
@ -286,8 +288,11 @@ impl Datacell {
None
}
}
unsafe fn load_word<'a, T: WordRW<NativeQword, Target<'a> = T>>(&'a self) -> T {
self.data.word.dword_ld()
unsafe fn load_word<'a, T>(&'a self) -> T
where
NativeQword: WordIO<T>,
{
self.data.word.load()
}
unsafe fn _new(tag: CUTag, data: DataRaw, init: bool) -> Self {
Self { init, tag, data }
@ -400,7 +405,7 @@ impl Clone for Datacell {
// UNSAFE(@ohsayan): we have checked that the cell is initialized (uninit will not satisfy this class), and we have checked its class
let mut block = ManuallyDrop::new(self.read_bin().to_owned().into_boxed_slice());
DataRaw {
word: ManuallyDrop::new(SystemDword::store((block.len(), block.as_mut_ptr()))),
word: ManuallyDrop::new(WordIO::store((block.len(), block.as_mut_ptr()))),
}
},
TagClass::List => unsafe {
@ -411,7 +416,7 @@ impl Clone for Datacell {
}
},
_ => unsafe {
// UNSAFE(@ohsayan): we have checked that the cell is initialized (uninit will not satisfy this class), and we have checked its class
// UNSAFE(@ohsayan): we have checked that the cell is a stack class
DataRaw {
word: ManuallyDrop::new(mem::transmute_copy(&self.data.word)),
}

@ -29,7 +29,7 @@ use {
spec::{Dataspec1D, DataspecMeta1D, DataspecMethods1D, DataspecRaw1D},
tag::{DataTag, FullTag, TagUnique},
},
crate::engine::mem::{SpecialPaddedWord, SystemDword},
crate::engine::mem::{DwordQN, SpecialPaddedWord, WordIO},
core::{
fmt,
hash::{Hash, Hasher},
@ -93,16 +93,16 @@ unsafe impl<'a> DataspecRaw1D for Lit<'a> {
const HEAP_STR: bool = true;
const HEAP_BIN: bool = false;
unsafe fn drop_str(&mut self) {
let [len, ptr] = self.data().load_double();
drop(String::from_raw_parts(ptr as *mut u8, len, len));
let (len, ptr) = self.data().load();
drop(String::from_raw_parts(ptr, len, len));
}
unsafe fn drop_bin(&mut self) {}
unsafe fn clone_str(s: &str) -> Self::Target {
let new_string = ManuallyDrop::new(s.to_owned().into_boxed_str());
SystemDword::store((new_string.len(), new_string.as_ptr()))
WordIO::store((new_string.len(), new_string.as_ptr()))
}
unsafe fn clone_bin(b: &[u8]) -> Self::Target {
SystemDword::store((b.len(), b.as_ptr()))
WordIO::store((b.len(), b.as_ptr()))
}
}
@ -114,7 +114,7 @@ unsafe impl<'a> DataspecRaw1D for Lit<'a> {
unsafe impl<'a> Dataspec1D for Lit<'a> {
fn Str(s: Box<str>) -> Self {
let md = ManuallyDrop::new(s);
Self::new(FullTag::STR, SystemDword::store((md.len(), md.as_ptr())))
Self::new(FullTag::STR, WordIO::store((md.len(), md.as_ptr())))
}
}
@ -184,8 +184,8 @@ pub struct LitIR<'a> {
impl<'a> LitIR<'a> {
pub fn __vdata(&self) -> &[u8] {
let [vlen, data] = self.data().load_double();
let len = vlen * (self.kind().tag_unique() >= TagUnique::Bin) as usize;
let (vlen, data) = self.data().dwordqn_load_qw_nw();
let len = vlen as usize * (self.kind().tag_unique() >= TagUnique::Bin) as usize;
unsafe {
// UNSAFE(@ohsayan): either because of static or lt
slice::from_raw_parts(data as *const u8, len)
@ -237,10 +237,10 @@ unsafe impl<'a> DataspecRaw1D for LitIR<'a> {
unsafe fn drop_str(&mut self) {}
unsafe fn drop_bin(&mut self) {}
unsafe fn clone_str(s: &str) -> Self::Target {
SystemDword::store((s.len(), s.as_ptr()))
WordIO::store((s.len(), s.as_ptr()))
}
unsafe fn clone_bin(b: &[u8]) -> Self::Target {
SystemDword::store((b.len(), b.as_ptr()))
WordIO::store((b.len(), b.as_ptr()))
}
}
@ -250,7 +250,7 @@ unsafe impl<'a> DataspecRaw1D for LitIR<'a> {
*/
unsafe impl<'a> Dataspec1D for LitIR<'a> {
fn Str(s: Self::StringItem) -> Self {
Self::new(FullTag::STR, SystemDword::store((s.len(), s.as_ptr())))
Self::new(FullTag::STR, WordIO::store((s.len(), s.as_ptr())))
}
}

@ -31,7 +31,7 @@
use {
super::tag::{DataTag, TagClass},
crate::engine::mem::SystemDword,
crate::engine::mem::{DwordQN, WordIO},
core::{fmt, mem, slice},
};
@ -45,7 +45,7 @@ pub trait DataspecMeta1D: Sized {
// assoc
type Tag: DataTag;
/// The target must be able to store (atleast) a native dword
type Target: SystemDword;
type Target: DwordQN;
/// The string item. This helps us remain correct with the dtors
type StringItem;
// fn
@ -86,27 +86,27 @@ pub unsafe trait Dataspec1D: DataspecMeta1D + DataspecRaw1D {
/// Store a new bool. This function is always safe to call
#[allow(non_snake_case)]
fn Bool(b: bool) -> Self {
Self::new(Self::Tag::BOOL, SystemDword::store(b))
Self::new(Self::Tag::BOOL, WordIO::store(b))
}
/// Store a new uint. This function is always safe to call
#[allow(non_snake_case)]
fn UnsignedInt(u: u64) -> Self {
Self::new(Self::Tag::UINT, SystemDword::store(u))
Self::new(Self::Tag::UINT, WordIO::store(u))
}
/// Store a new sint. This function is always safe to call
#[allow(non_snake_case)]
fn SignedInt(s: i64) -> Self {
Self::new(Self::Tag::SINT, SystemDword::store(s))
Self::new(Self::Tag::SINT, WordIO::store(s))
}
/// Store a new float. This function is always safe to call
#[allow(non_snake_case)]
fn Float(f: f64) -> Self {
Self::new(Self::Tag::FLOAT, SystemDword::store(f.to_bits()))
Self::new(Self::Tag::FLOAT, WordIO::store(f.to_bits()))
}
/// Store a new binary. This function is always safe to call
#[allow(non_snake_case)]
fn Bin(b: &[u8]) -> Self {
Self::new(Self::Tag::BIN, SystemDword::store((b.len(), b.as_ptr())))
Self::new(Self::Tag::BIN, WordIO::store((b.len(), b.as_ptr())))
}
/// Store a new string. Now, I won't talk about this one's safety because it depends on the implementor
@ -117,7 +117,7 @@ pub unsafe trait Dataspec1D: DataspecMeta1D + DataspecRaw1D {
// bool
/// Load a bool (this is unsafe for logical verity)
unsafe fn read_bool_uck(&self) -> bool {
self.data().dword_ld()
self.data().load()
}
/// Load a bool
fn read_bool_try(&self) -> Option<bool> {
@ -135,7 +135,7 @@ pub unsafe trait Dataspec1D: DataspecMeta1D + DataspecRaw1D {
// uint
/// Load a uint (this is unsafe for logical verity)
unsafe fn read_uint_uck(&self) -> u64 {
self.data().dword_ld()
self.data().load()
}
/// Load a uint
fn read_uint_try(&self) -> Option<u64> {
@ -156,7 +156,7 @@ pub unsafe trait Dataspec1D: DataspecMeta1D + DataspecRaw1D {
// sint
/// Load a sint (unsafe for logical verity)
unsafe fn read_sint_uck(&self) -> i64 {
self.data().dword_ld()
self.data().load()
}
/// Load a sint
fn read_sint_try(&self) -> Option<i64> {
@ -172,7 +172,7 @@ pub unsafe trait Dataspec1D: DataspecMeta1D + DataspecRaw1D {
// float
/// Load a float (unsafe for logical verity)
unsafe fn read_float_uck(&self) -> f64 {
self.data().dword_ld()
self.data().load()
}
/// Load a float
fn read_float_try(&self) -> Option<f64> {
@ -190,7 +190,7 @@ pub unsafe trait Dataspec1D: DataspecMeta1D + DataspecRaw1D {
/// ## Safety
/// Are you a binary? Did you store it correctly? Are you a victim of segfaults?
unsafe fn read_bin_uck(&self) -> &[u8] {
let (l, p) = self.data().dword_ld();
let (l, p) = self.data().load();
slice::from_raw_parts(p, l)
}
/// Load a bin

@ -35,7 +35,7 @@ mod tests;
pub use astr::AStr;
pub use uarray::UArray;
pub use vinline::VInline;
pub use word::{SystemDword, SystemQword, SystemTword, WordRW};
pub use word::{DwordNN, DwordQN, QwordNNNN, TwordNNN, WordIO};
// imports
use std::alloc::{self, Layout};
@ -58,7 +58,7 @@ pub struct SpecialPaddedWord {
}
impl SpecialPaddedWord {
const fn new(a: u64, b: usize) -> Self {
pub const unsafe fn new(a: u64, b: usize) -> Self {
Self { a, b }
}
}

@ -25,6 +25,7 @@
*/
use super::*;
mod word;
mod vinline {
use super::VInline;

@ -0,0 +1,145 @@
/*
* Created on Mon Apr 24 2023
*
* This file is a part of Skytable
* Skytable (formerly known as TerrabaseDB or Skybase) is a free and open-source
* NoSQL database written by Sayan Nandan ("the Author") with the
* vision to provide flexibility in data modelling without compromising
* on performance, queryability or scalability.
*
* Copyright (c) 2023, Sayan Nandan <ohsayan@outlook.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
use {
crate::engine::mem::{
word::{DwordQN, QwordNNNN, TwordNNN, WordIO, ZERO_BLOCK},
NativeDword, NativeQword, NativeTword, SpecialPaddedWord,
},
core::{slice, str},
};
fn wordld<T: PartialEq, W: WordIO<T>>(w: &W, x: T) -> (T, T) {
(w.load(), x)
}
macro_rules! assert_wordeq {
($a:expr, $b:expr) => {{
let (a, b) = wordld(&$a, $b);
assert_eq!(a, b);
}};
}
macro_rules! assert_wordeq_minmax {
($word:ty => $($ty:ty),* $(,)?; with $extramin:ident, $extramax:ident) => {{
$(
let x = <$word>::store(<$ty>::MIN); assert_wordeq!(x, <$ty>::MIN);
$extramin(&x);
let x = <$word>::store(<$ty>::MAX); assert_wordeq!(x, <$ty>::MAX);
$extramax(&x);
)*
}};
}
fn check_primitives<W>(extramin: impl Fn(&W), extramax: impl Fn(&W))
where
W: WordIO<bool>
+ WordIO<u8>
+ WordIO<u16>
+ WordIO<u32>
+ WordIO<u64>
+ WordIO<i8>
+ WordIO<i16>
+ WordIO<i32>
+ WordIO<i64>
+ WordIO<f32>
+ WordIO<f64>
+ WordIO<(usize, usize)>
+ WordIO<(usize, *mut u8)>
+ WordIO<(usize, *const u8)>,
{
assert_wordeq_minmax!(W => u8, u16, u32, u64, i8, i16, i32, i64, f32, f64; with extramin, extramax);
// bool
let x = W::store(false);
assert_wordeq!(x, false);
extramin(&x);
let x = W::store(true);
assert_wordeq!(x, true);
extramax(&x);
// str
let str = "hello, world";
let x = W::store((str.len(), str.as_ptr()));
unsafe {
let (len, ptr) = x.load();
assert_eq!(
str,
str::from_utf8_unchecked(slice::from_raw_parts(ptr, len))
);
}
// string (mut)
let mut string = String::from("hello, world");
let x = W::store((string.len(), string.as_mut_ptr()));
unsafe {
let (len, ptr) = x.load();
assert_eq!(
string,
str::from_utf8_unchecked(slice::from_raw_parts(ptr, len))
);
}
}
#[test]
fn dwordnn_all() {
check_primitives::<NativeDword>(|_| {}, |_| {});
}
#[test]
fn dwordqn_all() {
check_primitives::<SpecialPaddedWord>(
|minword| {
let (_a, b) = minword.dwordqn_load_qw_nw();
assert_eq!(b, ZERO_BLOCK.as_ptr() as usize);
},
|maxword| {
let (_a, b) = maxword.dwordqn_load_qw_nw();
assert_eq!(b, ZERO_BLOCK.as_ptr() as usize);
},
);
}
#[test]
fn twordnnn_all() {
check_primitives::<NativeTword>(|_| {}, |_| {});
}
#[test]
fn qwordnnn_all() {
check_primitives::<NativeQword>(|_| {}, |_| {});
}
#[test]
fn dwordqn_promotions() {
let x = SpecialPaddedWord::store(u64::MAX);
let y: NativeTword = x.dword_promote();
let (uint, usize) = y.dwordqn_load_qw_nw();
assert_eq!(uint, u64::MAX);
assert_eq!(usize, ZERO_BLOCK.as_ptr() as usize);
let z: NativeQword = y.tword_promote();
let (uint, usize_1, usize_2) = z.qwordnnnn_load_qw_nw_nw();
assert_eq!(uint, u64::MAX);
assert_eq!(usize_1, ZERO_BLOCK.as_ptr() as usize);
assert_eq!(usize_2, 0);
}

@ -24,9 +24,12 @@
*
*/
use super::{NativeDword, NativeQword, NativeTword, SpecialPaddedWord};
use {
super::{NativeDword, NativeQword, NativeTword, SpecialPaddedWord},
core::mem::size_of,
};
static ZERO_BLOCK: [u8; 0] = [];
pub static ZERO_BLOCK: [u8; 0] = [];
#[cfg(target_pointer_width = "32")]
fn quadsplit(q: u64) -> [usize; 2] {
@ -43,353 +46,333 @@ fn quadmerge(v: [usize; 2]) -> u64 {
}
}
/// Native quad pointer stack (must also be usable as a double and triple pointer stack. see [`SystemTword`] and [`SystemDword`])
pub trait SystemQword: SystemTword {
fn store_full(a: usize, b: usize, c: usize, d: usize) -> Self;
fn load_quad(&self) -> [usize; 4];
fn store<'a, T>(v: T) -> Self
where
T: WordRW<Self>,
{
WordRW::store(v)
}
fn qword_ld<'a, T>(&'a self) -> T
where
T: WordRW<Self, Target<'a> = T>,
{
<T>::load(self)
pub trait WordIO<T> {
fn store(v: T) -> Self;
fn load(&self) -> T;
}
/*
dword
---
kinds: NN (word * 2), QN (qword, word)
promotions: QN -> NNN
*/
pub trait DwordNN: Sized {
const DWORDNN_FROM_UPPER: bool = size_of::<Self>() > size_of::<[usize; 2]>();
fn dwordnn_store_native_full(a: usize, b: usize) -> Self;
fn dwordnn_store_qw(a: u64) -> Self {
debug_assert!(!Self::DWORDNN_FROM_UPPER, "NEED TO OVERRIDE STORE");
#[cfg(target_pointer_width = "32")]
{
let [a, b] = quadsplit(a);
Self::dwordnn_store_native_full(a, b)
}
#[cfg(target_pointer_width = "64")]
{
Self::dwordnn_store_native_full(a as usize, 0)
}
}
fn dwordnn_load_native_full(&self) -> [usize; 2];
fn dwordnn_load_qw(&self) -> u64 {
debug_assert!(!Self::DWORDNN_FROM_UPPER, "NEED TO OVERRIDE LOAD");
#[cfg(target_pointer_width = "32")]
{
quadmerge(self.dwordnn_load_native_full())
}
#[cfg(target_pointer_width = "64")]
{
self.dwordnn_load_native_full()[0] as u64
}
}
}
/// Native tripe pointer stack (must also be usable as a double pointer stack, see [`SystemDword`])
pub trait SystemTword: SystemDword {
/// Store a quad and a native word
fn store_qw_nw(a: u64, b: usize) -> Self;
/// Load a quad and a native word
fn load_qw_nw(&self) -> (u64, usize);
fn store_full(a: usize, b: usize, c: usize) -> Self;
fn load_triple(&self) -> [usize; 3];
fn store<'a, T>(v: T) -> Self
where
T: WordRW<Self>,
{
WordRW::store(v)
}
fn tword_ld<'a, T>(&'a self) -> T
where
T: WordRW<Self, Target<'a> = T>,
{
<T>::load(self)
pub trait DwordQN: Sized {
const DWORDQN_FROM_UPPER: bool = size_of::<Self>() > size_of::<(u64, usize)>();
fn dwordqn_store_qw_nw(a: u64, b: usize) -> Self;
fn dwordqn_load_qw_nw(&self) -> (u64, usize);
// overrides
fn overridable_dwordnn_store_qw(a: u64) -> Self {
Self::dwordqn_store_qw_nw(a, 0)
}
// promotions
fn dword_promote<W: DwordQN>(&self) -> W {
let (a, b) = self.dwordqn_load_qw_nw();
<W as DwordQN>::dwordqn_store_qw_nw(a, b)
}
}
/// Native double pointer stack
pub trait SystemDword: Sized {
fn store_qw(u: u64) -> Self;
fn store_fat(a: usize, b: usize) -> Self;
fn load_qw(&self) -> u64;
fn load_double(&self) -> [usize; 2];
fn store<'a, T>(v: T) -> Self
where
T: WordRW<Self>,
{
WordRW::store(v)
}
fn dword_ld<'a, T>(&'a self) -> T
where
T: WordRW<Self, Target<'a> = T>,
{
<T>::load(self)
/*
dword: blanket impls
*/
impl<T: DwordQN> DwordNN for T {
fn dwordnn_store_native_full(a: usize, b: usize) -> Self {
Self::dwordqn_store_qw_nw(a as u64, b)
}
fn dwordnn_store_qw(a: u64) -> Self {
Self::overridable_dwordnn_store_qw(a)
}
fn dwordnn_load_native_full(&self) -> [usize; 2] {
let (a, b) = self.dwordqn_load_qw_nw();
debug_assert!(a <= usize::MAX as u64, "overflowed with: `{}`", a);
[a as usize, b]
}
fn dwordnn_load_qw(&self) -> u64 {
DwordQN::dwordqn_load_qw_nw(self).0
}
}
impl SystemDword for SpecialPaddedWord {
fn store_qw(u: u64) -> Self {
Self::new(u, ZERO_BLOCK.as_ptr() as usize)
/*
dword: impls
*/
impl DwordNN for NativeDword {
fn dwordnn_store_native_full(a: usize, b: usize) -> Self {
Self([a, b])
}
fn store_fat(a: usize, b: usize) -> Self {
Self::new(a as u64, b)
fn dwordnn_load_native_full(&self) -> [usize; 2] {
self.0
}
fn load_qw(&self) -> u64 {
self.a
}
impl DwordQN for SpecialPaddedWord {
fn dwordqn_store_qw_nw(a: u64, b: usize) -> Self {
unsafe {
// UNSAFE(@ohsayan): valid construction
Self::new(a, b)
}
}
fn dwordqn_load_qw_nw(&self) -> (u64, usize) {
(self.a, self.b)
}
// overrides
fn overridable_dwordnn_store_qw(a: u64) -> Self {
unsafe {
// UNSAFE(@ohsayan): valid construction
Self::new(a, ZERO_BLOCK.as_ptr() as usize)
}
}
fn load_double(&self) -> [usize; 2] {
[self.a as usize, self.b]
}
/*
tword
---
kinds: NNN (word * 3)
promotions: NNN -> NNNN
*/
pub trait TwordNNN: Sized {
const TWORDNNN_FROM_UPPER: bool = size_of::<Self>() > size_of::<[usize; 3]>();
fn twordnnn_store_native_full(a: usize, b: usize, c: usize) -> Self;
fn twordnnn_load_native_full(&self) -> [usize; 3];
// promotions
fn tword_promote<W: TwordNNN>(&self) -> W {
let [a, b, c] = self.twordnnn_load_native_full();
<W as TwordNNN>::twordnnn_store_native_full(a, b, c)
}
}
impl SystemDword for NativeDword {
#[inline(always)]
fn store_qw(u: u64) -> Self {
let x;
/*
tword: blanket impls
*/
impl<T: TwordNNN> DwordQN for T {
fn dwordqn_store_qw_nw(a: u64, b: usize) -> Self {
#[cfg(target_pointer_width = "32")]
{
x = quadsplit(u);
let [qw_1, qw_2] = quadsplit(a);
Self::twordnnn_store_native_full(qw_1, qw_2, b)
}
#[cfg(target_pointer_width = "64")]
{
x = [u as usize, 0]
Self::twordnnn_store_native_full(a as usize, b, 0)
}
Self(x)
}
#[inline(always)]
fn store_fat(a: usize, b: usize) -> Self {
Self([a, b])
}
#[inline(always)]
fn load_qw(&self) -> u64 {
let x;
fn dwordqn_load_qw_nw(&self) -> (u64, usize) {
#[cfg(target_pointer_width = "32")]
{
x = quadmerge(self.0);
let [w1, w2, b] = self.twordnnn_load_native_full();
(quadmerge([w1, w2]), b)
}
#[cfg(target_pointer_width = "64")]
{
x = self.0[0] as _;
let [a, b, _] = self.twordnnn_load_native_full();
(a as u64, b)
}
x
}
#[inline(always)]
fn load_double(&self) -> [usize; 2] {
self.0
}
}
impl SystemTword for NativeTword {
#[inline(always)]
fn store_full(a: usize, b: usize, c: usize) -> Self {
/*
tword: impls
*/
impl TwordNNN for NativeTword {
fn twordnnn_store_native_full(a: usize, b: usize, c: usize) -> Self {
Self([a, b, c])
}
#[inline(always)]
fn load_triple(&self) -> [usize; 3] {
fn twordnnn_load_native_full(&self) -> [usize; 3] {
self.0
}
#[inline(always)]
fn store_qw_nw(a: u64, b: usize) -> Self {
let ret;
}
/*
qword
---
kinds: NNNN (word * 4)
promotions: N/A
*/
pub trait QwordNNNN: Sized {
const QWORDNNNN_FROM_UPPER: bool = size_of::<Self>() > size_of::<[usize; 4]>();
fn qwordnnnn_store_native_full(a: usize, b: usize, c: usize, d: usize) -> Self;
fn qwordnnnn_store_qw_qw(a: u64, b: u64) -> Self {
#[cfg(target_pointer_width = "32")]
{
let [qw_1, qw_2] = quadsplit(a);
ret = [qw_1, qw_2, b];
let [qw1_a, qw1_b] = quadsplit(a);
let [qw2_a, qw2_b] = quadsplit(b);
Self::qwordnnnn_store_native_full(qw1_a, qw1_b, qw2_a, qw2_b)
}
#[cfg(target_pointer_width = "64")]
{
ret = [a as usize, b, 0];
Self::qwordnnnn_store_native_full(a as usize, b as usize, 0, 0)
}
Self(ret)
}
#[inline(always)]
fn load_qw_nw(&self) -> (u64, usize) {
let ret;
fn qwordnnnn_store_qw_nw_nw(a: u64, b: usize, c: usize) -> Self {
#[cfg(target_pointer_width = "32")]
{
let qw = quadmerge([self.0[0], self.0[1]]);
let nw = self.0[2];
ret = (qw, nw);
let [qw_a, qw_b] = quadsplit(a);
Self::qwordnnnn_store_native_full(qw_a, qw_b, b, c)
}
#[cfg(target_pointer_width = "64")]
{
ret = (self.0[0] as u64, self.0[1]);
Self::qwordnnnn_store_native_full(a as usize, b, c, 0)
}
ret
}
}
impl SystemDword for NativeTword {
#[inline(always)]
fn store_qw(u: u64) -> Self {
let x;
fn qwordnnnn_load_native_full(&self) -> [usize; 4];
fn qwordnnnn_load_qw_qw(&self) -> [u64; 2] {
let [a, b, c, d] = self.qwordnnnn_load_native_full();
#[cfg(target_pointer_width = "32")]
{
let [a, b]: [usize; 2] = quadsplit(u);
x = [a, b, 0];
[quadmerge([a, b]), quadmerge([c, d])]
}
#[cfg(target_pointer_width = "64")]
{
x = [u as _, 0, 0];
let _ = (c, d);
[a as u64, b as u64]
}
Self(x)
}
#[inline(always)]
fn store_fat(a: usize, b: usize) -> Self {
Self([a, b, 0])
}
#[inline(always)]
fn load_qw(&self) -> u64 {
let x;
fn qwordnnnn_load_qw_nw_nw(&self) -> (u64, usize, usize) {
let [a, b, c, d] = self.qwordnnnn_load_native_full();
#[cfg(target_pointer_width = "32")]
{
x = quadmerge([self.0[0], self.0[1]]);
(quadmerge([a, b]), c, d)
}
#[cfg(target_pointer_width = "64")]
{
x = self.0[0] as _;
let _ = d;
(a as u64, b, c)
}
x
}
#[inline(always)]
fn load_double(&self) -> [usize; 2] {
[self.0[0], self.0[1]]
}
/*
qword: blanket impls
*/
impl<T: QwordNNNN> TwordNNN for T {
fn twordnnn_store_native_full(a: usize, b: usize, c: usize) -> Self {
Self::qwordnnnn_store_native_full(a, b, c, 0)
}
fn twordnnn_load_native_full(&self) -> [usize; 3] {
let [a, b, c, _] = self.qwordnnnn_load_native_full();
[a, b, c]
}
}
impl SystemQword for NativeQword {
fn store_full(a: usize, b: usize, c: usize, d: usize) -> Self {
/*
qword: impls
*/
impl QwordNNNN for NativeQword {
fn qwordnnnn_store_native_full(a: usize, b: usize, c: usize, d: usize) -> Self {
Self([a, b, c, d])
}
fn load_quad(&self) -> [usize; 4] {
fn qwordnnnn_load_native_full(&self) -> [usize; 4] {
self.0
}
}
impl SystemTword for NativeQword {
fn store_full(a: usize, b: usize, c: usize) -> Self {
Self([a, b, c, 0])
/*
impls: WordIO
*/
macro_rules! impl_numeric_io {
($trait:ident => { $($ty:ty),* $(,)? }) => {
$(impl<T: $trait> WordIO<$ty> for T {
fn store(v: $ty) -> Self { Self::dwordnn_store_qw(v as _) }
fn load(&self) -> $ty { self.dwordnn_load_qw() as _ }
})*
}
fn load_triple(&self) -> [usize; 3] {
[self.0[0], self.0[1], self.0[2]]
}
impl_numeric_io!(DwordNN => { u8, u16, u32, u64, i8, i16, i32, i64 });
impl<T: DwordNN> WordIO<bool> for T {
fn store(v: bool) -> Self {
Self::dwordnn_store_qw(v as _)
}
/// Store a quadword and a native word
fn store_qw_nw(a: u64, b: usize) -> Self {
let ret;
#[cfg(target_pointer_width = "32")]
{
let [qw_1, qw_2] = quadsplit(a);
ret = [qw_1, qw_2, b, 0];
}
#[cfg(target_pointer_width = "64")]
{
ret = [a as usize, b, 0, 0];
}
Self(ret)
}
#[inline(always)]
fn load_qw_nw(&self) -> (u64, usize) {
let ret;
#[cfg(target_pointer_width = "32")]
{
let qw = quadmerge([self.0[0], self.0[1]]);
let nw = self.0[2];
ret = (qw, nw);
}
#[cfg(target_pointer_width = "64")]
{
ret = (self.0[0] as u64, self.0[1]);
}
ret
fn load(&self) -> bool {
self.dwordnn_load_qw() == 1
}
}
impl SystemDword for NativeQword {
fn store_qw(u: u64) -> Self {
let ret;
#[cfg(target_pointer_width = "32")]
{
let [a, b] = quadsplit(u);
ret = <Self as SystemQword>::store_full(a, b, 0, 0);
}
#[cfg(target_pointer_width = "64")]
{
ret = <Self as SystemQword>::store_full(u as _, 0, 0, 0);
}
ret
}
fn store_fat(a: usize, b: usize) -> Self {
<Self as SystemQword>::store_full(a, b, 0, 0)
macro_rules! impl_float_io {
($($float:ty),* $(,)?) => {
$(impl<T: DwordNN> WordIO<$float> for T {
fn store(v: $float) -> Self { Self::dwordnn_store_qw(v.to_bits() as u64) }
fn load(&self) -> $float { <$float>::from_bits(self.dwordnn_load_qw() as _) }
})*
}
fn load_qw(&self) -> u64 {
let ret;
#[cfg(target_pointer_width = "32")]
{
ret = quadmerge([self.0[0], self.0[1]]);
}
#[cfg(target_pointer_width = "64")]
{
ret = self.0[0] as _;
}
ret
}
impl_float_io!(f32, f64);
impl<T: DwordNN> WordIO<(usize, usize)> for T {
fn store((a, b): (usize, usize)) -> Self {
Self::dwordnn_store_native_full(a, b)
}
fn load_double(&self) -> [usize; 2] {
[self.0[0], self.0[1]]
fn load(&self) -> (usize, usize) {
let [a, b] = self.dwordnn_load_native_full();
(a, b)
}
}
pub trait WordRW<W> {
type Target<'a>
where
W: 'a;
fn store(self) -> W;
fn load<'a>(word: &'a W) -> Self::Target<'a>;
impl<T: DwordNN> WordIO<[usize; 2]> for T {
fn store([a, b]: [usize; 2]) -> Self {
Self::dwordnn_store_native_full(a, b)
}
fn load(&self) -> [usize; 2] {
self.dwordnn_load_native_full()
}
}
macro_rules! impl_wordrw {
($($ty:ty as $minword:ident => { type Target<'a> = $target:ty; |$selfname:ident| $store:expr; |$wordarg:ident| $load:expr;})*) => {
$(impl<W: $minword> WordRW<W> for $ty { type Target<'a> = $target where W: 'a; fn store($selfname: Self) -> W { $store } fn load<'a>($wordarg: &'a W) -> Self::Target<'a> { $load } })*
};
($($ty:ty as $minword:ident => { |$selfname:ident| $store:expr; |$wordarg:ident| $load:expr;})*) => { impl_wordrw!($($ty as $minword => { type Target<'a> = $ty; |$selfname| $store; |$wordarg| $load;})*); };
impl<T: DwordNN> WordIO<(usize, *mut u8)> for T {
fn store((a, b): (usize, *mut u8)) -> Self {
Self::dwordnn_store_native_full(a, b as usize)
}
fn load(&self) -> (usize, *mut u8) {
let [a, b] = self.dwordnn_load_native_full();
(a, b as *mut u8)
}
}
impl_wordrw! {
bool as SystemDword => {
|self| SystemDword::store_qw(self as _);
|word| SystemDword::load_qw(word) == 1;
}
u8 as SystemDword => {
|self| SystemDword::store_qw(self as _);
|word| SystemDword::load_qw(word) as u8;
}
u16 as SystemDword => {
|self| SystemDword::store_qw(self as _);
|word| SystemDword::load_qw(word) as u16;
}
u32 as SystemDword => {
|self| SystemDword::store_qw(self as _);
|word| SystemDword::load_qw(word) as u32;
}
u64 as SystemDword => {
|self| SystemDword::store_qw(self);
|word| SystemDword::load_qw(word);
}
i8 as SystemDword => {
|self| SystemDword::store_qw(self as _);
|word| SystemDword::load_qw(word) as i8;
}
i16 as SystemDword => {
|self| SystemDword::store_qw(self as _);
|word| SystemDword::load_qw(word) as i16;
}
i32 as SystemDword => {
|self| SystemDword::store_qw(self as _);
|word| SystemDword::load_qw(word) as i32;
}
i64 as SystemDword => {
|self| SystemDword::store_qw(self as _);
|word| SystemDword::load_qw(word) as i64;
}
f32 as SystemDword => {
|self| SystemDword::store_qw(self.to_bits() as u64);
|word| f32::from_bits(SystemDword::load_qw(word) as u32);
}
f64 as SystemDword => {
|self| SystemDword::store_qw(self.to_bits());
|word| f64::from_bits(SystemDword::load_qw(word));
}
[usize; 2] as SystemDword => {
|self| SystemDword::store_fat(self[0], self[1]);
|word| SystemDword::load_double(word);
}
(usize, *mut u8) as SystemDword => {
|self| SystemDword::store_fat(self.0, self.1 as usize);
|word| {
let [a, b] = word.load_double();
(a, b as *mut u8)
};
}
(usize, *const u8) as SystemDword => {
|self| SystemDword::store_fat(self.0, self.1 as usize);
|word| {
let [a, b] = word.load_double();
(a, b as *const u8)
};
impl<T: DwordNN> WordIO<(usize, *const u8)> for T {
fn store((a, b): (usize, *const u8)) -> Self {
Self::dwordnn_store_native_full(a, b as usize)
}
fn load(&self) -> (usize, *const u8) {
let [a, b] = self.dwordnn_load_native_full();
(a, b as *const u8)
}
}

Loading…
Cancel
Save