forked from M-Labs/artiq
Backport of "fixes alignment and size problem" from artiq-zynq (#1841)
This commit is contained in:
parent
93328ad8ee
commit
34008b7a21
|
@ -5,15 +5,20 @@ use byteorder::{NativeEndian, ByteOrder};
|
||||||
use io::{ProtoRead, Read, Write, ProtoWrite, Error};
|
use io::{ProtoRead, Read, Write, ProtoWrite, Error};
|
||||||
use self::tag::{Tag, TagIterator, split_tag};
|
use self::tag::{Tag, TagIterator, split_tag};
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn alignment_offset(alignment: isize, ptr: isize) -> isize {
|
||||||
|
(-ptr).rem_euclid(alignment)
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn align_ptr<T>(ptr: *const ()) -> *const T {
|
unsafe fn align_ptr<T>(ptr: *const ()) -> *const T {
|
||||||
let alignment = core::mem::align_of::<T>() as isize;
|
let alignment = core::mem::align_of::<T>() as isize;
|
||||||
let fix = (alignment - (ptr as isize) % alignment) % alignment;
|
let fix = alignment_offset(alignment as isize, ptr as isize);
|
||||||
((ptr as isize) + fix) as *const T
|
((ptr as isize) + fix) as *const T
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn align_ptr_mut<T>(ptr: *mut ()) -> *mut T {
|
unsafe fn align_ptr_mut<T>(ptr: *mut ()) -> *mut T {
|
||||||
let alignment = core::mem::align_of::<T>() as isize;
|
let alignment = core::mem::align_of::<T>() as isize;
|
||||||
let fix = (alignment - (ptr as isize) % alignment) % alignment;
|
let fix = alignment_offset(alignment as isize, ptr as isize);
|
||||||
((ptr as isize) + fix) as *mut T
|
((ptr as isize) + fix) as *mut T
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,6 +59,7 @@ unsafe fn recv_value<R, E>(reader: &mut R, tag: Tag, data: &mut *mut (),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Tag::Tuple(it, arity) => {
|
Tag::Tuple(it, arity) => {
|
||||||
|
*data = data.offset(alignment_offset(tag.alignment() as isize, *data as isize));
|
||||||
let mut it = it.clone();
|
let mut it = it.clone();
|
||||||
for _ in 0..arity {
|
for _ in 0..arity {
|
||||||
let tag = it.next().expect("truncated tag");
|
let tag = it.next().expect("truncated tag");
|
||||||
|
@ -69,9 +75,12 @@ unsafe fn recv_value<R, E>(reader: &mut R, tag: Tag, data: &mut *mut (),
|
||||||
let length = (*ptr).length as usize;
|
let length = (*ptr).length as usize;
|
||||||
|
|
||||||
let tag = it.clone().next().expect("truncated tag");
|
let tag = it.clone().next().expect("truncated tag");
|
||||||
(*ptr).elements = alloc(tag.size() * (*ptr).length as usize)?;
|
let padding = if let Tag::Int64 | Tag::Float64 = tag { 4 } else { 0 };
|
||||||
|
let mut data = alloc(tag.size() * length + padding)?;
|
||||||
|
|
||||||
let mut data = (*ptr).elements;
|
data = data.offset(alignment_offset(tag.alignment() as isize, data as isize));
|
||||||
|
|
||||||
|
(*ptr).elements = data;
|
||||||
match tag {
|
match tag {
|
||||||
Tag::Bool => {
|
Tag::Bool => {
|
||||||
let dest = slice::from_raw_parts_mut(data as *mut u8, length);
|
let dest = slice::from_raw_parts_mut(data as *mut u8, length);
|
||||||
|
@ -109,9 +118,11 @@ unsafe fn recv_value<R, E>(reader: &mut R, tag: Tag, data: &mut *mut (),
|
||||||
let length = total_len as usize;
|
let length = total_len as usize;
|
||||||
|
|
||||||
let elt_tag = it.clone().next().expect("truncated tag");
|
let elt_tag = it.clone().next().expect("truncated tag");
|
||||||
*buffer = alloc(elt_tag.size() * total_len as usize)?;
|
let padding = if let Tag::Int64 | Tag::Float64 = tag { 4 } else { 0 };
|
||||||
|
let mut data = alloc(elt_tag.size() * length + padding)?;
|
||||||
|
data = data.offset(alignment_offset(tag.alignment() as isize, data as isize));
|
||||||
|
|
||||||
let mut data = *buffer;
|
*buffer = data;
|
||||||
match elt_tag {
|
match elt_tag {
|
||||||
Tag::Bool => {
|
Tag::Bool => {
|
||||||
let dest = slice::from_raw_parts_mut(data as *mut u8, length);
|
let dest = slice::from_raw_parts_mut(data as *mut u8, length);
|
||||||
|
@ -139,6 +150,7 @@ unsafe fn recv_value<R, E>(reader: &mut R, tag: Tag, data: &mut *mut (),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Tag::Range(it) => {
|
Tag::Range(it) => {
|
||||||
|
*data = data.offset(alignment_offset(tag.alignment() as isize, *data as isize));
|
||||||
let tag = it.clone().next().expect("truncated tag");
|
let tag = it.clone().next().expect("truncated tag");
|
||||||
recv_value(reader, tag, data, alloc)?;
|
recv_value(reader, tag, data, alloc)?;
|
||||||
recv_value(reader, tag, data, alloc)?;
|
recv_value(reader, tag, data, alloc)?;
|
||||||
|
@ -336,6 +348,7 @@ pub fn send_args<W>(writer: &mut W, service: u32, tag_bytes: &[u8], data: *const
|
||||||
|
|
||||||
mod tag {
|
mod tag {
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
|
use super::alignment_offset;
|
||||||
|
|
||||||
pub fn split_tag(tag_bytes: &[u8]) -> (&[u8], &[u8]) {
|
pub fn split_tag(tag_bytes: &[u8]) -> (&[u8], &[u8]) {
|
||||||
let tag_separator =
|
let tag_separator =
|
||||||
|
@ -385,6 +398,33 @@ mod tag {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn alignment(self) -> usize {
|
||||||
|
use cslice::CSlice;
|
||||||
|
match self {
|
||||||
|
Tag::None => 1,
|
||||||
|
Tag::Bool => core::mem::align_of::<u8>(),
|
||||||
|
Tag::Int32 => core::mem::align_of::<i32>(),
|
||||||
|
Tag::Int64 => core::mem::align_of::<i64>(),
|
||||||
|
Tag::Float64 => core::mem::align_of::<f64>(),
|
||||||
|
// struct type: align to largest element
|
||||||
|
Tag::Tuple(it, arity) => {
|
||||||
|
let it = it.clone();
|
||||||
|
it.take(arity.into()).map(|t| t.alignment()).max().unwrap()
|
||||||
|
},
|
||||||
|
Tag::Range(it) => {
|
||||||
|
let it = it.clone();
|
||||||
|
it.take(3).map(|t| t.alignment()).max().unwrap()
|
||||||
|
}
|
||||||
|
// CSlice basically
|
||||||
|
Tag::Bytes | Tag::String | Tag::ByteArray | Tag::List(_) =>
|
||||||
|
core::mem::align_of::<CSlice<()>>(),
|
||||||
|
// array buffer is allocated, so no need for alignment first
|
||||||
|
Tag::Array(_, _) => 1,
|
||||||
|
// will not be sent from the host
|
||||||
|
_ => unreachable!("unexpected tag from host")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn size(self) -> usize {
|
pub fn size(self) -> usize {
|
||||||
match self {
|
match self {
|
||||||
Tag::None => 0,
|
Tag::None => 0,
|
||||||
|
@ -401,6 +441,7 @@ mod tag {
|
||||||
for _ in 0..arity {
|
for _ in 0..arity {
|
||||||
let tag = it.next().expect("truncated tag");
|
let tag = it.next().expect("truncated tag");
|
||||||
size += tag.size();
|
size += tag.size();
|
||||||
|
size += alignment_offset(tag.alignment() as isize, size as isize) as usize;
|
||||||
}
|
}
|
||||||
size
|
size
|
||||||
}
|
}
|
||||||
|
@ -469,6 +510,13 @@ mod tag {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator for TagIterator<'a> {
|
||||||
|
type Item = Tag<'a>;
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
(self as &mut TagIterator<'a>).next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> fmt::Display for TagIterator<'a> {
|
impl<'a> fmt::Display for TagIterator<'a> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
let mut it = self.clone();
|
let mut it = self.clone();
|
||||||
|
|
|
@ -515,3 +515,26 @@ class NumpyBoolTest(ExperimentCase):
|
||||||
def test_numpy_bool(self):
|
def test_numpy_bool(self):
|
||||||
"""Test NumPy bools decay to ARTIQ compiler builtin bools as expected"""
|
"""Test NumPy bools decay to ARTIQ compiler builtin bools as expected"""
|
||||||
self.create(_NumpyBool).run()
|
self.create(_NumpyBool).run()
|
||||||
|
|
||||||
|
|
||||||
|
class _Alignment(EnvExperiment):
|
||||||
|
def build(self):
|
||||||
|
self.setattr_device("core")
|
||||||
|
|
||||||
|
@rpc
|
||||||
|
def a_tuple(self) -> TList(TTuple([TBool, TFloat, TBool])):
|
||||||
|
return [(True, 1234.5678, True)]
|
||||||
|
|
||||||
|
@kernel
|
||||||
|
def run(self):
|
||||||
|
a, b, c = self.a_tuple()[0]
|
||||||
|
d, e, f = self.a_tuple()[0]
|
||||||
|
assert a == d
|
||||||
|
assert b == e
|
||||||
|
assert c == f
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
class AlignmentTest(ExperimentCase):
|
||||||
|
def test_tuple(self):
|
||||||
|
self.create(_Alignment).run()
|
||||||
|
|
Loading…
Reference in New Issue