From 6f9f455152a6b71a0535008cb23f251739029a0d Mon Sep 17 00:00:00 2001 From: ychenfo Date: Wed, 2 Feb 2022 03:19:11 +0800 Subject: [PATCH] nac3core: list slice irrt use one function to handle var size --- nac3core/src/codegen/irrt/irrt.c | 86 ++++---------------------------- nac3core/src/codegen/irrt/mod.rs | 62 +++++++---------------- 2 files changed, 28 insertions(+), 120 deletions(-) diff --git a/nac3core/src/codegen/irrt/irrt.c b/nac3core/src/codegen/irrt/irrt.c index 7381fac7c..fe3169920 100644 --- a/nac3core/src/codegen/irrt/irrt.c +++ b/nac3core/src/codegen/irrt/irrt.c @@ -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 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) -# 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 dest_start, 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_ind += src_step, dest_ind += dest_step ) { - /* memcpy for var size, cannot overlap after previous alloca */ - __builtin_memcpy(dest_arr + dest_ind * size, src_arr + src_ind * size, size); + /* for constant optimization */ + 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. */ /* size should be ensured prior to calling this function */ diff --git a/nac3core/src/codegen/irrt/mod.rs b/nac3core/src/codegen/irrt/mod.rs index 88450f97b..f6c5b989c 100644 --- a/nac3core/src/codegen/irrt/mod.rs +++ b/nac3core/src/codegen/irrt/mod.rs @@ -237,30 +237,9 @@ pub fn list_slice_assignment<'ctx, 'a>( ) { let int8_ptr = ctx.ctx.i8_type().ptr_type(AddressSpace::Generic); let int32 = ctx.ctx.i32_type(); - let int32_ptr = int32.ptr_type(AddressSpace::Generic); - 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 (fun_symbol, elem_ptr_type) = ("__nac3_list_slice_assign_var_size", int8_ptr); let slice_assign_fun = { - let mut ty_vec = vec![ + let ty_vec = vec![ int32.into(), // dest start idx int32.into(), // dest end idx int32.into(), // dest step @@ -271,17 +250,10 @@ pub fn list_slice_assignment<'ctx, 'a>( int32.into(), // src step elem_ptr_type.into(), // src arr ptr int32.into(), // src arr len + int32.into(), // size ]; ctx.module.get_function(fun_symbol).unwrap_or_else(|| { - let fn_t = int32.fn_type( - { - if fun_symbol == "__nac3_list_slice_assign_var_size" { - ty_vec.push(int32.into()); - } - ty_vec.as_slice() - }, - false, - ); + let fn_t = int32.fn_type(ty_vec.as_slice(), false); 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 // throw exception if not satisfied let new_len = { - let mut args = vec![ + let args = vec![ dest_idx.0.into(), // dest start idx dest_idx.1.into(), // dest end idx dest_idx.2.into(), // dest step @@ -320,20 +292,20 @@ pub fn list_slice_assignment<'ctx, 'a>( src_idx.2.into(), // src step src_arr_ptr.into(), // src arr ptr 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 - .build_call( - 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", - ) + .build_call(slice_assign_fun, args.as_slice(), "slice_assign") .try_as_basic_value() .unwrap_left() .into_int_value()