forked from M-Labs/nac3
nac3core: list slice irrt use one function to handle var size
This commit is contained in:
parent
e50f1017fa
commit
6f9f455152
|
@ -57,79 +57,6 @@ int32_t __nac3_range_slice_len(const int32_t start, const int32_t end, const int
|
||||||
// - The end index is *inclusive*,
|
// - The end index is *inclusive*,
|
||||||
// - The length of src and dest slice size should already
|
// - The length of src and dest slice size should already
|
||||||
// be checked: if dest.step == 1 then len(src) <= len(dest) else len(src) == len(dest)
|
// be checked: if dest.step == 1 then len(src) <= len(dest) else len(src) == len(dest)
|
||||||
# define DEF_SLICE_ASSIGN(T) int32_t __nac3_list_slice_assign_##T( \
|
|
||||||
int32_t dest_start, \
|
|
||||||
int32_t dest_end, \
|
|
||||||
int32_t dest_step, \
|
|
||||||
T *dest_arr, \
|
|
||||||
int32_t dest_arr_len, \
|
|
||||||
int32_t src_start, \
|
|
||||||
int32_t src_end, \
|
|
||||||
int32_t src_step, \
|
|
||||||
T *src_arr, \
|
|
||||||
int32_t src_arr_len \
|
|
||||||
) { \
|
|
||||||
/* if dest_arr_len == 0, do nothing since we do not support extending list */ \
|
|
||||||
if (dest_arr_len == 0) return dest_arr_len; \
|
|
||||||
/* if both step is 1, memmove directly, handle the dropping of the list, and shrink size */ \
|
|
||||||
if (src_step == dest_step && dest_step == 1) { \
|
|
||||||
const int32_t src_len = (src_end >= src_start) ? (src_end - src_start + 1) : 0; \
|
|
||||||
const int32_t dest_len = (dest_end >= dest_start) ? (dest_end - dest_start + 1) : 0; \
|
|
||||||
if (src_len > 0) { \
|
|
||||||
__builtin_memmove( \
|
|
||||||
dest_arr + dest_start, \
|
|
||||||
src_arr + src_start, \
|
|
||||||
src_len * sizeof(T) \
|
|
||||||
); \
|
|
||||||
} \
|
|
||||||
if (dest_len > 0) { \
|
|
||||||
/* dropping */ \
|
|
||||||
__builtin_memmove( \
|
|
||||||
dest_arr + dest_start + src_len, \
|
|
||||||
dest_arr + dest_end + 1, \
|
|
||||||
(dest_arr_len - dest_end - 1) * sizeof(T) \
|
|
||||||
); \
|
|
||||||
} \
|
|
||||||
/* shrink size */ \
|
|
||||||
return dest_arr_len - (dest_len - src_len); \
|
|
||||||
} \
|
|
||||||
/* if two range overlaps, need alloca */ \
|
|
||||||
uint8_t need_alloca = \
|
|
||||||
(dest_arr == src_arr) \
|
|
||||||
&& !( \
|
|
||||||
MAX(dest_start, dest_end) < MIN(src_start, src_end) \
|
|
||||||
|| MAX(src_start, src_end) < MIN(dest_start, dest_end) \
|
|
||||||
); \
|
|
||||||
if (need_alloca) { \
|
|
||||||
T *tmp = alloca(src_arr_len * sizeof(T)); \
|
|
||||||
__builtin_memcpy(tmp, src_arr, src_arr_len * sizeof(T)); \
|
|
||||||
src_arr = tmp; \
|
|
||||||
} \
|
|
||||||
int32_t src_ind = src_start; \
|
|
||||||
int32_t dest_ind = dest_start; \
|
|
||||||
for (; \
|
|
||||||
(src_step > 0) ? (src_ind <= src_end) : (src_ind >= src_end); \
|
|
||||||
src_ind += src_step, dest_ind += dest_step \
|
|
||||||
) { \
|
|
||||||
dest_arr[dest_ind] = src_arr[src_ind]; \
|
|
||||||
} \
|
|
||||||
/* only dest_step == 1 can we shrink the dest list. */ \
|
|
||||||
/* size should be ensured prior to calling this function */ \
|
|
||||||
if (dest_step == 1 && dest_end >= dest_start) { \
|
|
||||||
__builtin_memmove( \
|
|
||||||
dest_arr + dest_ind, \
|
|
||||||
dest_arr + dest_end + 1, \
|
|
||||||
(dest_arr_len - dest_end - 1) * sizeof(T) \
|
|
||||||
); \
|
|
||||||
return dest_arr_len - (dest_end - dest_ind) - 1; \
|
|
||||||
} \
|
|
||||||
return dest_arr_len; \
|
|
||||||
} \
|
|
||||||
|
|
||||||
DEF_SLICE_ASSIGN(uint8_t)
|
|
||||||
DEF_SLICE_ASSIGN(uint32_t)
|
|
||||||
DEF_SLICE_ASSIGN(uint64_t)
|
|
||||||
|
|
||||||
int32_t __nac3_list_slice_assign_var_size(
|
int32_t __nac3_list_slice_assign_var_size(
|
||||||
int32_t dest_start,
|
int32_t dest_start,
|
||||||
int32_t dest_end,
|
int32_t dest_end,
|
||||||
|
@ -185,8 +112,17 @@ int32_t __nac3_list_slice_assign_var_size(
|
||||||
(src_step > 0) ? (src_ind <= src_end) : (src_ind >= src_end);
|
(src_step > 0) ? (src_ind <= src_end) : (src_ind >= src_end);
|
||||||
src_ind += src_step, dest_ind += dest_step
|
src_ind += src_step, dest_ind += dest_step
|
||||||
) {
|
) {
|
||||||
/* memcpy for var size, cannot overlap after previous alloca */
|
/* for constant optimization */
|
||||||
__builtin_memcpy(dest_arr + dest_ind * size, src_arr + src_ind * size, size);
|
if (size == 1) {
|
||||||
|
__builtin_memcpy(dest_arr + dest_ind, src_arr + src_ind, 1);
|
||||||
|
} else if (size == 4) {
|
||||||
|
__builtin_memcpy(dest_arr + dest_ind * 4, src_arr + src_ind * 4, 4);
|
||||||
|
} else if (size == 8) {
|
||||||
|
__builtin_memcpy(dest_arr + dest_ind * 8, src_arr + src_ind * 8, 8);
|
||||||
|
} else {
|
||||||
|
/* memcpy for var size, cannot overlap after previous alloca */
|
||||||
|
__builtin_memcpy(dest_arr + dest_ind * size, src_arr + src_ind * size, size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* only dest_step == 1 can we shrink the dest list. */
|
/* only dest_step == 1 can we shrink the dest list. */
|
||||||
/* size should be ensured prior to calling this function */
|
/* size should be ensured prior to calling this function */
|
||||||
|
|
|
@ -237,30 +237,9 @@ pub fn list_slice_assignment<'ctx, 'a>(
|
||||||
) {
|
) {
|
||||||
let int8_ptr = ctx.ctx.i8_type().ptr_type(AddressSpace::Generic);
|
let int8_ptr = ctx.ctx.i8_type().ptr_type(AddressSpace::Generic);
|
||||||
let int32 = ctx.ctx.i32_type();
|
let int32 = ctx.ctx.i32_type();
|
||||||
let int32_ptr = int32.ptr_type(AddressSpace::Generic);
|
let (fun_symbol, elem_ptr_type) = ("__nac3_list_slice_assign_var_size", int8_ptr);
|
||||||
let int64_ptr = ctx.ctx.i64_type().ptr_type(AddressSpace::Generic);
|
|
||||||
let elem_size = match ty {
|
|
||||||
BasicTypeEnum::IntType(ty) => match ty.get_bit_width() {
|
|
||||||
w if w < 32 => Some(8),
|
|
||||||
w if w == 32 || w == 64 => Some(w),
|
|
||||||
_ => unreachable!(),
|
|
||||||
},
|
|
||||||
BasicTypeEnum::FloatType(_) => Some(64),
|
|
||||||
BasicTypeEnum::PointerType(_) => match size_ty.get_bit_width() {
|
|
||||||
w if w == 32 || w == 64 => Some(w),
|
|
||||||
_ => unreachable!(),
|
|
||||||
},
|
|
||||||
BasicTypeEnum::StructType(_) => None,
|
|
||||||
_ => unreachable!(),
|
|
||||||
};
|
|
||||||
let (fun_symbol, elem_ptr_type) = match elem_size {
|
|
||||||
Some(8) => ("__nac3_list_slice_assign_uint8_t", int8_ptr),
|
|
||||||
Some(32) => ("__nac3_list_slice_assign_uint32_t", int32_ptr),
|
|
||||||
Some(64) => ("__nac3_list_slice_assign_uint64_t", int64_ptr),
|
|
||||||
_ => ("__nac3_list_slice_assign_var_size", int8_ptr),
|
|
||||||
};
|
|
||||||
let slice_assign_fun = {
|
let slice_assign_fun = {
|
||||||
let mut ty_vec = vec![
|
let ty_vec = vec![
|
||||||
int32.into(), // dest start idx
|
int32.into(), // dest start idx
|
||||||
int32.into(), // dest end idx
|
int32.into(), // dest end idx
|
||||||
int32.into(), // dest step
|
int32.into(), // dest step
|
||||||
|
@ -271,17 +250,10 @@ pub fn list_slice_assignment<'ctx, 'a>(
|
||||||
int32.into(), // src step
|
int32.into(), // src step
|
||||||
elem_ptr_type.into(), // src arr ptr
|
elem_ptr_type.into(), // src arr ptr
|
||||||
int32.into(), // src arr len
|
int32.into(), // src arr len
|
||||||
|
int32.into(), // size
|
||||||
];
|
];
|
||||||
ctx.module.get_function(fun_symbol).unwrap_or_else(|| {
|
ctx.module.get_function(fun_symbol).unwrap_or_else(|| {
|
||||||
let fn_t = int32.fn_type(
|
let fn_t = int32.fn_type(ty_vec.as_slice(), false);
|
||||||
{
|
|
||||||
if fun_symbol == "__nac3_list_slice_assign_var_size" {
|
|
||||||
ty_vec.push(int32.into());
|
|
||||||
}
|
|
||||||
ty_vec.as_slice()
|
|
||||||
},
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
ctx.module.add_function(fun_symbol, fn_t, None)
|
ctx.module.add_function(fun_symbol, fn_t, None)
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
@ -309,7 +281,7 @@ pub fn list_slice_assignment<'ctx, 'a>(
|
||||||
// TODO: assert if dest.step == 1 then len(src) <= len(dest) else len(src) == len(dest), and
|
// TODO: assert if dest.step == 1 then len(src) <= len(dest) else len(src) == len(dest), and
|
||||||
// throw exception if not satisfied
|
// throw exception if not satisfied
|
||||||
let new_len = {
|
let new_len = {
|
||||||
let mut args = vec![
|
let args = vec![
|
||||||
dest_idx.0.into(), // dest start idx
|
dest_idx.0.into(), // dest start idx
|
||||||
dest_idx.1.into(), // dest end idx
|
dest_idx.1.into(), // dest end idx
|
||||||
dest_idx.2.into(), // dest step
|
dest_idx.2.into(), // dest step
|
||||||
|
@ -320,20 +292,20 @@ pub fn list_slice_assignment<'ctx, 'a>(
|
||||||
src_idx.2.into(), // src step
|
src_idx.2.into(), // src step
|
||||||
src_arr_ptr.into(), // src arr ptr
|
src_arr_ptr.into(), // src arr ptr
|
||||||
src_len.into(), // src arr len
|
src_len.into(), // src arr len
|
||||||
|
{
|
||||||
|
let s = match ty {
|
||||||
|
BasicTypeEnum::FloatType(t) => t.size_of(),
|
||||||
|
BasicTypeEnum::IntType(t) => t.size_of(),
|
||||||
|
BasicTypeEnum::PointerType(t) => t.size_of(),
|
||||||
|
BasicTypeEnum::StructType(t) => t.size_of().unwrap(),
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
ctx.builder.build_int_truncate_or_bit_cast(s, int32, "size")
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
];
|
];
|
||||||
ctx.builder
|
ctx.builder
|
||||||
.build_call(
|
.build_call(slice_assign_fun, args.as_slice(), "slice_assign")
|
||||||
slice_assign_fun,
|
|
||||||
{
|
|
||||||
if fun_symbol == "__nac3_list_slice_assign_var_size" {
|
|
||||||
let s = ty.into_struct_type().size_of().unwrap();
|
|
||||||
let s = ctx.builder.build_int_truncate_or_bit_cast(s, int32, "size");
|
|
||||||
args.push(s.into());
|
|
||||||
}
|
|
||||||
args.as_slice()
|
|
||||||
},
|
|
||||||
"slice_assign",
|
|
||||||
)
|
|
||||||
.try_as_basic_value()
|
.try_as_basic_value()
|
||||||
.unwrap_left()
|
.unwrap_left()
|
||||||
.into_int_value()
|
.into_int_value()
|
||||||
|
|
Loading…
Reference in New Issue