Some arrays will always have the same size - a static size.
Others might have a different size each time their scope is entered, if
the size is calculates from a variable.
The latter need to be reallocated whenever scope is entered, the former
do not.
This will matter when we create call frames to be able to handle
recursion.
So detect and handle the difference now.
Signed-off-by: NeilBrown <neil@brown.name>
struct type *next;
int size, align;
void (*init)(struct type *type, struct value *val);
struct type *next;
int size, align;
void (*init)(struct type *type, struct value *val);
- void (*prepare_type)(struct type *type);
+ void (*prepare_type)(struct type *type, int parse_time);
void (*print)(struct type *type, struct value *val);
void (*print_type)(struct type *type, FILE *f);
int (*cmp_order)(struct type *t1, struct type *t2,
void (*print)(struct type *type, struct value *val);
void (*print_type)(struct type *type, FILE *f);
int (*cmp_order)(struct type *t1, struct type *t2,
struct value *ret;
if (t->prepare_type)
struct value *ret;
if (t->prepare_type)
ret = calloc(1, t->size);
if (init)
ret = calloc(1, t->size);
if (init)
a "`copy`" primitive will eventually be define which can be used to
make a copy of an array with controllable recursive depth.
a "`copy`" primitive will eventually be define which can be used to
make a copy of an array with controllable recursive depth.
+For now we have two sorts of array, those with fixed size either because
+it is given as a literal number or because it is a struct member (which
+cannot have a runtime-changing size), and those with a size that is
+determined at runtime - local variables with a const size. The former
+have their size calculated at parse time, the latter at run time.
+
+For the latter type, the `size` field of the type is the size of a
+pointer, and the array is reallocated every time it comes into scope.
+
+We differentiate struct fields with a const size from local variables
+with a const size by whether they are prepared at parse time or not.
+
###### type union fields
struct {
###### type union fields
struct {
+ short size;
+ short static_size;
struct variable *vsize;
struct type *member;
} array;
struct variable *vsize;
struct type *member;
} array;
+###### value union fields
+ void *array; // used if not static_size
+
- static void array_prepare_type(struct type *type)
+ static void array_prepare_type(struct type *type, int parse_time)
- if (!type->array.vsize)
+ if (!type->array.vsize || type->array.static_size)
type->array.size = mpz_get_si(q);
mpz_clear(q);
type->array.size = mpz_get_si(q);
mpz_clear(q);
- type->size = type->array.size * type->array.member->size;
- type->align = type->array.member->align;
+ if (parse_time) {
+ type->array.static_size = 1;
+ type->size = type->array.size * type->array.member->size;
+ type->align = type->array.member->align;
+ }
}
static void array_init(struct type *type, struct value *val)
{
int i;
}
static void array_init(struct type *type, struct value *val)
{
int i;
+ return;
+ if (!type->array.static_size) {
+ val->array = calloc(type->array.size,
+ type->array.member->size);
+ ptr = val->array;
+ }
for (i = 0; i < type->array.size; i++) {
struct value *v;
for (i = 0; i < type->array.size; i++) {
struct value *v;
- v = (void*)val->ptr + i * type->array.member->size;
+ v = (void*)ptr + i * type->array.member->size;
val_init(type->array.member, v);
}
}
val_init(type->array.member, v);
}
}
static void array_free(struct type *type, struct value *val)
{
int i;
static void array_free(struct type *type, struct value *val)
{
int i;
+ if (!type->array.static_size)
+ ptr = val->array;
for (i = 0; i < type->array.size; i++) {
struct value *v;
for (i = 0; i < type->array.size; i++) {
struct value *v;
- v = (void*)val->ptr + i * type->array.member->size;
+ v = (void*)ptr + i * type->array.member->size;
free_value(type->array.member, v);
}
free_value(type->array.member, v);
}
+ if (!type->array.static_size)
+ free(ptr);
}
static int array_compat(struct type *require, struct type *have)
}
static int array_compat(struct type *require, struct type *have)
.print_type = array_print_type,
.compat = array_compat,
.free = array_free,
.print_type = array_print_type,
.compat = array_compat,
.free = array_free,
+ .size = sizeof(void*),
+ .align = sizeof(void*),
};
###### declare terminals
};
###### declare terminals
+ t->array.static_size = 1;
t->size = t->array.size * t->array.member->size;
t->align = t->array.member->align;
} }$
t->size = t->array.size * t->array.member->size;
t->align = t->array.member->align;
} }$
case Index: {
mpz_t q;
long i;
case Index: {
mpz_t q;
long i;
lleft = linterp_exec(b->left, <ype);
right = interp_exec(b->right, &rtype);
lleft = linterp_exec(b->left, <ype);
right = interp_exec(b->right, &rtype);
i = mpz_get_si(q);
mpz_clear(q);
i = mpz_get_si(q);
mpz_clear(q);
+ if (ltype->array.static_size)
+ ptr = lleft;
+ else
+ ptr = *(void**)lleft;
rvtype = ltype->array.member;
if (i >= 0 && i < ltype->array.size)
rvtype = ltype->array.member;
if (i >= 0 && i < ltype->array.size)
- lrv = (void*)lleft + i * rvtype->size;
+ lrv = ptr + i * rvtype->size;
else
val_init(ltype->array.member, &rv);
ltype = NULL;
else
val_init(ltype->array.member, &rv);
ltype = NULL;
$0->f.name = $1.txt;
$0->f.type = $<3;
if ($0->f.type->prepare_type)
$0->f.name = $1.txt;
$0->f.type = $<3;
if ($0->f.type->prepare_type)
- $0->f.type->prepare_type($0->f.type);
+ $0->f.type->prepare_type($0->f.type, 1);