diff --git a/mie/dialect/builtin/attribute/array.c b/mie/dialect/builtin/attribute/array.c index b31cace..76ae04c 100644 --- a/mie/dialect/builtin/attribute/array.c +++ b/mie/dialect/builtin/attribute/array.c @@ -73,7 +73,7 @@ static enum mie_status parse( return MIE_ERR_BAD_FORMAT; } - mie_vector_push_back(array->a_items, &item); + mie_vector_push_back(array->a_items, &item, NULL); while (1) { if (mie_parser_parse_symbol(ctx, MIE_SYM_RIGHT_BRACKET)) { @@ -89,7 +89,7 @@ static enum mie_status parse( return MIE_ERR_BAD_FORMAT; } - mie_vector_push_back(array->a_items, &item); + mie_vector_push_back(array->a_items, &item, NULL); } *out = (struct mie_attribute *)array; diff --git a/mie/include/mie/vector.h b/mie/include/mie/vector.h index f782fbd..8b16e35 100644 --- a/mie/include/mie/vector.h +++ b/mie/include/mie/vector.h @@ -2,14 +2,14 @@ #define MIE_VECTOR_H_ #include +#include #include -#if 0 -#define MIE_VECTOR_DEFINE(type, name) \ - size_t name##_count = 0; \ - size_t name##_max = 0; \ - type *name = NULL -#endif +struct mie_vector_ops { + enum mie_status (*v_copy)(void *, const void *, size_t); + enum mie_status (*v_move)(void *, void *, size_t); + enum mie_status (*v_destroy)(void *); +}; #define MIE_VECTOR_DEFINE(type, name) \ struct { \ @@ -43,52 +43,65 @@ #define MIE_VECTOR_REF2(name) &(name.items), &(name.count), &(name.max) /* use these functions if you're accessing a vector directly. */ -#define mie_vector_push_back(vector, ptr) \ +#define mie_vector_push_back(vector, ptr, ops) \ __mie_vector_push_back( \ (void **)&(vector.items), ptr, sizeof *ptr, &(vector.count), \ - &(vector.max)) -#define mie_vector_pop_back(vector) \ + &(vector.max), ops) +#define mie_vector_pop_back(vector, ops) \ __mie_vector_pop_back( \ (void **)&(vector), sizeof *vector, &(vector.count), \ - &(vector.max)) -#define mie_vector_emplace_back(vector) \ + &(vector.max), ops) +#define mie_vector_emplace_back(vector, ops) \ __mie_vector_emplace_back( \ (void **)&(vector.items), sizeof *vector.items, \ - &(vector.count), &(vector.max)) -#define mie_vector_destroy(vector, dtor) \ + &(vector.count), &(vector.max), ops) +#define mie_vector_trim(vector, ops) \ + __mie_vector_trim( \ + (void **)&(vector.items), sizeof *vector.items, \ + &(vector.count), &(vector.max), ops) +#define mie_vector_destroy(vector, ops) \ __mie_vector_destroy( \ (void **)&(vector.items), sizeof *vector.items, \ - &(vector.count), &(vector.max), dtor) + &(vector.count), &(vector.max), ops) /* use these functions if you're accessing a vector as a reference * via MIE_VECTOR_REF_PARAM. */ -#define mie_vector_ref_push_back(vector, ptr) \ +#define mie_vector_ref_push_back(vector, ptr, ops) \ __mie_vector_push_back( \ (void **)(vector), ptr, sizeof *ptr, (vector##_count), \ - (vector##_max)) -#define mie_vector_ref_pop_back(vector) \ + (vector##_max), ops) +#define mie_vector_ref_pop_back(vector, ops) \ __mie_vector_pop_back( \ (void **)(vector), sizeof **vector, (vector##_count), \ - (vector##_max)) -#define mie_vector_ref_emplace_back(vector) \ + (vector##_max), ops) +#define mie_vector_ref_emplace_back(vector, ops) \ __mie_vector_emplace_back( \ (void **)(vector), sizeof **vector, (vector##_count), \ - (vector##_max)) -#define mie_vector_ref_destroy(vector, dtor) \ + (vector##_max), ops) +#define mie_vector_ref_trim(vector, ops) \ + __mie_vector_trim( \ + (void **)(vector), sizeof **vector, (vector##_count), \ + (vector##_max), ops) +#define mie_vector_ref_destroy(vector, ops) \ __mie_vector_destroy( \ (void **)(vector), sizeof **vector, (vector##_count), \ - (vector##_max), dtor) + (vector##_max), ops) /* don't use these functions */ MIE_API int __mie_vector_push_back( void **vector, const void *item, size_t item_size, size_t *count, - size_t *max); + size_t *max, const struct mie_vector_ops *ops); MIE_API void __mie_vector_pop_back( - void **vector, size_t item_size, size_t *count, size_t *max); + void **vector, size_t item_size, size_t *count, size_t *max, + const struct mie_vector_ops *ops); MIE_API void *__mie_vector_emplace_back( - void **vector, size_t item_size, size_t *count, size_t *max); + void **vector, size_t item_size, size_t *count, size_t *max, + const struct mie_vector_ops *ops); +MIE_API void __mie_vector_trim( + void **vector, size_t item_size, size_t *count, size_t *max, + const struct mie_vector_ops *ops); MIE_API void __mie_vector_destroy( void **vector, size_t item_size, size_t *count, size_t *max, - void (*dtor)(void *)); + const struct mie_vector_ops *ops); #endif diff --git a/mie/ir/region.c b/mie/ir/region.c index 4dab861..3300240 100644 --- a/mie/ir/region.c +++ b/mie/ir/region.c @@ -12,7 +12,7 @@ struct mie_block *mie_region_add_block(struct mie_region *region) memset(block, 0x0, sizeof *block); - mie_vector_push_back(region->r_blocks, &block); + mie_vector_push_back(region->r_blocks, &block, NULL); return block; } diff --git a/mie/parse/parser.c b/mie/parse/parser.c index 3781877..e0ec63d 100644 --- a/mie/parse/parser.c +++ b/mie/parse/parser.c @@ -398,7 +398,7 @@ static bool parse_composite_type(struct mie_parser *ctx, const struct mie_type * ok = mie_parser_parse_type(ctx, &temp); if (temp) { - mie_vector_push_back(type_list_2, &temp); + mie_vector_push_back(type_list_2, &temp, NULL); } } @@ -449,13 +449,13 @@ bool mie_parser_parse_type_list( return true; } - type_slot = mie_vector_ref_emplace_back(out); + type_slot = mie_vector_ref_emplace_back(out, NULL); if (!type_slot) { return false; } if (!mie_parser_parse_type(ctx, type_slot)) { - mie_vector_ref_pop_back(out); + mie_vector_ref_pop_back(out, NULL); return false; } @@ -464,13 +464,13 @@ bool mie_parser_parse_type_list( break; } - type_slot = mie_vector_ref_emplace_back(out); + type_slot = mie_vector_ref_emplace_back(out, NULL); if (!type_slot) { return false; } if (!mie_parser_parse_type(ctx, type_slot)) { - mie_vector_ref_pop_back(out); + mie_vector_ref_pop_back(out, NULL); return false; } } @@ -506,7 +506,7 @@ MIE_API bool mie_parser_parse_function_type( ok = mie_parser_parse_type(ctx, &type); if (type) { - mie_vector_push_back(out_parts, &type); + mie_vector_push_back(out_parts, &type, NULL); } } @@ -558,7 +558,7 @@ bool mie_parser_parse_operand_list( return false; } - operand = mie_vector_ref_emplace_back(out); + operand = mie_vector_ref_emplace_back(out, NULL); if (!operand) { return false; } @@ -582,7 +582,7 @@ bool mie_parser_parse_operand_list( return false; } - operand = mie_vector_ref_emplace_back(out); + operand = mie_vector_ref_emplace_back(out, NULL); if (!operand) { return false; } @@ -634,7 +634,7 @@ bool mie_parser_parse_parameter_list( return false; } - operand = mie_vector_ref_emplace_back(out); + operand = mie_vector_ref_emplace_back(out, NULL); if (!operand) { return false; } @@ -658,7 +658,7 @@ bool mie_parser_parse_parameter_list( return false; } - operand = mie_vector_ref_emplace_back(out); + operand = mie_vector_ref_emplace_back(out, NULL); if (!operand) { return false; } @@ -733,7 +733,7 @@ bool mie_parser_parse_register_list( return false; } - mie_vector_ref_push_back(out, ®); + mie_vector_ref_push_back(out, ®, NULL); if (!mie_parser_parse_register(ctx, names, reg)) { return false; @@ -758,7 +758,7 @@ bool mie_parser_parse_register_list( if (!reg) { return false; } - mie_vector_ref_push_back(out, ®); + mie_vector_ref_push_back(out, ®, NULL); if (!mie_parser_parse_register(ctx, names, reg)) { return false; @@ -812,7 +812,7 @@ bool mie_parser_parse_region_list( return false; } - struct mie_region *region = mie_vector_ref_emplace_back(out); + struct mie_region *region = mie_vector_ref_emplace_back(out, NULL); if (!mie_parser_parse_region(ctx, region)) { return false; @@ -827,7 +827,7 @@ bool mie_parser_parse_region_list( break; } - struct mie_region *region = mie_vector_ref_emplace_back(out); + struct mie_region *region = mie_vector_ref_emplace_back(out, NULL); if (!mie_parser_parse_region(ctx, region)) { return false; @@ -842,7 +842,7 @@ bool mie_parser_parse_anonymous_block( { mie_parser_parse_linefeed(ctx); - struct mie_op *op = mie_vector_emplace_back(block->b_ops); + struct mie_op *op = mie_vector_emplace_back(block->b_ops, NULL); mie_op_init(op); if (!mie_parser_parse_op(ctx, names, op)) { @@ -860,7 +860,7 @@ bool mie_parser_parse_anonymous_block( break; } - struct mie_op *op = mie_vector_emplace_back(block->b_ops); + struct mie_op *op = mie_vector_emplace_back(block->b_ops, NULL); mie_op_init(op); if (!mie_parser_parse_op(ctx, names, op)) { @@ -899,7 +899,7 @@ static bool parse_block_parameters( for (size_t i = 0; i < MIE_VECTOR_COUNT(block_params); i++) { struct mie_register *param_reg = calloc(1, sizeof *param_reg); - mie_vector_push_back(block->b_params, ¶m_reg); + mie_vector_push_back(block->b_params, ¶m_reg, NULL); param_reg->reg_flags = block_params.items[i].arg_unresolved.reg_flags | MIE_REGISTER_F_BLOCK_PARAM; @@ -955,7 +955,7 @@ bool mie_parser_parse_block( break; } - struct mie_op *op = mie_vector_emplace_back(block->b_ops); + struct mie_op *op = mie_vector_emplace_back(block->b_ops, NULL); mie_op_init(op); if (!mie_parser_parse_op(ctx, names, op)) { return false; @@ -1019,7 +1019,7 @@ bool mie_parser_parse_successor_list( bool ok = false; struct mie_op_successor *successor = NULL; - successor = mie_vector_ref_emplace_back(out); + successor = mie_vector_ref_emplace_back(out, NULL); if (!successor) { return false; } @@ -1038,7 +1038,7 @@ bool mie_parser_parse_successor_list( mie_parser_advance(ctx); mie_parser_parse_linefeed(ctx); - successor = mie_vector_ref_emplace_back(out); + successor = mie_vector_ref_emplace_back(out, NULL); if (!successor) { return false; } diff --git a/mie/pass/pass-manager.c b/mie/pass/pass-manager.c index fc11c00..f47ba7b 100644 --- a/mie/pass/pass-manager.c +++ b/mie/pass/pass-manager.c @@ -74,7 +74,7 @@ struct mie_pass_manager *mie_pass_manager_nest(struct mie_pass_manager *pm) struct mie_pass_manager *nest = mie_pass_manager_create(pm->pm_ctx); nest->pm_depth = pm->pm_depth + 1; - mie_vector_push_back(pm->pm_nested, &nest); + mie_vector_push_back(pm->pm_nested, &nest, NULL); return nest; } @@ -171,7 +171,7 @@ static bool filter_check_op( void mie_pass_manager_add_pass(struct mie_pass_manager *pm, struct mie_pass *pass) { - mie_vector_push_back(pm->pm_passes, &pass); + mie_vector_push_back(pm->pm_passes, &pass, NULL); } static void schedule_passes( diff --git a/mie/type/function.c b/mie/type/function.c index fbc651d..781ddb2 100644 --- a/mie/type/function.c +++ b/mie/type/function.c @@ -74,13 +74,13 @@ struct mie_function_type *mie_function_type_create(void) void mie_function_type_add_in_part( struct mie_function_type *ty, const struct mie_type *part) { - mie_vector_push_back(ty->func_in, &part); + mie_vector_push_back(ty->func_in, &part, NULL); } void mie_function_type_add_out_part( struct mie_function_type *ty, const struct mie_type *part) { - mie_vector_push_back(ty->func_out, &part); + mie_vector_push_back(ty->func_out, &part, NULL); } void mie_function_type_print( diff --git a/mie/type/storage.c b/mie/type/storage.c index 6afbc72..205f686 100644 --- a/mie/type/storage.c +++ b/mie/type/storage.c @@ -56,7 +56,7 @@ struct mie_storage_type *mie_storage_type_create(void) void mie_storage_type_add_part( struct mie_storage_type *ty, const struct mie_type *part) { - mie_vector_push_back(ty->st_parts, &part); + mie_vector_push_back(ty->st_parts, &part, NULL); } void mie_storage_type_build_id( diff --git a/mie/vector.c b/mie/vector.c index 4a24f3b..e9ddd83 100644 --- a/mie/vector.c +++ b/mie/vector.c @@ -30,26 +30,84 @@ static void vector_unwrap( *max = v->v_max; } -static int vector_reserve(struct vector *v, size_t new_capacity) +static int move_vector_items( + struct vector *v, void *new_buf, size_t new_capacity, + const struct mie_vector_ops *ops) +{ + size_t items_to_copy = MIN(v->v_count, new_capacity); + if (!ops || (!ops->v_copy && !ops->v_move)) { + memcpy(new_buf, v->v_buf, items_to_copy * v->v_itemsz); + return 0; + } + + char *src = v->v_buf; + char *dst = new_buf; + for (size_t i = 0; i < items_to_copy; i++) { + if (ops->v_move) { + ops->v_move(dst, src, v->v_itemsz); + } else if (ops->v_copy) { + ops->v_copy(dst, src, v->v_itemsz); + } else { + memcpy(dst, src, v->v_itemsz); + } + + src += v->v_itemsz; + dst += v->v_itemsz; + } + + return 0; +} + +static int trim_excess_items( + struct vector *v, size_t new_capacity, const struct mie_vector_ops *ops) +{ + size_t to_trim = v->v_count - new_capacity; + size_t start = new_capacity; + char *item = &v->v_buf[start]; + + for (size_t i = start; i < v->v_count; i++) { + ops->v_destroy(item); + item += v->v_itemsz; + } + + return 0; +} + +static int vector_resize( + struct vector *v, size_t new_capacity, const struct mie_vector_ops *ops) { if (v->v_max >= new_capacity) { return 0; } - void *ptr = realloc(v->v_buf, new_capacity * v->v_itemsz); - if (!ptr) { + void *new_buf = malloc(new_capacity * v->v_itemsz); + if (!new_buf) { return -1; } - v->v_buf = ptr; + move_vector_items(v, new_buf, new_capacity, ops); + if (ops && ops->v_destroy && new_capacity < v->v_count) { + trim_excess_items(v, new_capacity, ops); + } + + if (v->v_buf) { + free(v->v_buf); + } + + v->v_buf = new_buf; v->v_max = new_capacity; + if (new_capacity < v->v_count) { + v->v_count = new_capacity; + } + return 0; } -static int vector_push_back(struct vector *v, const void *item) +static int vector_push_back( + struct vector *v, const void *item, const struct mie_vector_ops *ops) { - int err = vector_reserve(v, v->v_count + DEFAULT_CAPACITY); + int err = vector_resize(v, v->v_count + DEFAULT_CAPACITY, ops); if (err != 0) { return err; } @@ -61,7 +119,7 @@ static int vector_push_back(struct vector *v, const void *item) return 0; } -static int vector_pop_back(struct vector *v) +static int vector_pop_back(struct vector *v, const struct mie_vector_ops *ops) { if (v->v_count > 0) { v->v_count--; @@ -70,9 +128,13 @@ static int vector_pop_back(struct vector *v) return 0; } -static void *vector_emplace_back(struct vector *v) +static void *vector_emplace_back(struct vector *v, const struct mie_vector_ops *ops) { - int err = vector_reserve(v, v->v_count + 1); + int err = 0; + if (v->v_count >= v->v_max) { + err = vector_resize(v, v->v_count + DEFAULT_CAPACITY, ops); + } + if (err != 0) { return NULL; } @@ -84,18 +146,25 @@ static void *vector_emplace_back(struct vector *v) return dest; } -static void vector_destroy_items(struct vector *v, void (*dtor)(void *)) +static void vector_destroy_items(struct vector *v, const struct mie_vector_ops *ops) { for (size_t i = 0; i < v->v_count; i++) { void *item = (char *)v->v_buf + (i * v->v_itemsz); - dtor(item); + ops->v_destroy(item); } } -static void vector_destroy(struct vector *v, void (*dtor)(void *)) +static void vector_trim(struct vector *v, const struct mie_vector_ops *ops) { - if (dtor) { - vector_destroy_items(v, dtor); + if (v->v_max > v->v_count) { + vector_resize(v, v->v_count, ops); + } +} + +static void vector_destroy(struct vector *v, const struct mie_vector_ops *ops) +{ + if (ops && ops->v_destroy) { + vector_destroy_items(v, ops); } if (v->v_buf) { @@ -109,47 +178,59 @@ static void vector_destroy(struct vector *v, void (*dtor)(void *)) int __mie_vector_push_back( void **vector, const void *item, size_t item_size, size_t *count, - size_t *max) + size_t *max, const struct mie_vector_ops *ops) { struct vector v = {}; int err = 0; vector_wrap(&v, vector, item_size, count, max); - err = vector_push_back(&v, item); + err = vector_push_back(&v, item, ops); vector_unwrap(&v, vector, item_size, count, max); return err; } void __mie_vector_pop_back( - void **vector, size_t item_size, size_t *count, size_t *max) + void **vector, size_t item_size, size_t *count, size_t *max, + const struct mie_vector_ops *ops) { struct vector v = {}; vector_wrap(&v, vector, item_size, count, max); - vector_pop_back(&v); + vector_pop_back(&v, ops); vector_unwrap(&v, vector, item_size, count, max); } void *__mie_vector_emplace_back( - void **vector, size_t item_size, size_t *count, size_t *max) + void **vector, size_t item_size, size_t *count, size_t *max, + const struct mie_vector_ops *ops) { struct vector v = {}; void *p = 0; vector_wrap(&v, vector, item_size, count, max); - p = vector_emplace_back(&v); + p = vector_emplace_back(&v, NULL); vector_unwrap(&v, vector, item_size, count, max); return p; } -void __mie_vector_destroy( +void __mie_vector_trim( void **vector, size_t item_size, size_t *count, size_t *max, - void (*dtor)(void *)) + const struct mie_vector_ops *ops) { struct vector v = {}; vector_wrap(&v, vector, item_size, count, max); - vector_destroy(&v, dtor); + vector_trim(&v, ops); + vector_unwrap(&v, vector, item_size, count, max); +} + +void __mie_vector_destroy( + void **vector, size_t item_size, size_t *count, size_t *max, + const struct mie_vector_ops *ops) +{ + struct vector v = {}; + vector_wrap(&v, vector, item_size, count, max); + vector_destroy(&v, ops); vector_unwrap(&v, vector, item_size, count, max); }