Skip to content

Commit

Permalink
Remove builtin functions for 'LENGTH, 'LEFT, etc.
Browse files Browse the repository at this point in the history
  • Loading branch information
nickg committed Apr 19, 2015
1 parent 93c7f50 commit 73f188f
Show file tree
Hide file tree
Showing 8 changed files with 360 additions and 223 deletions.
59 changes: 34 additions & 25 deletions src/bounds.c
Expand Up @@ -68,31 +68,6 @@ static tree_t bounds_check_call_args(tree_t t)
const int nparams = tree_params(t);
const int nports = tree_ports(decl);

// Check dimension argument of array attributes

ident_t builtin = tree_attr_str(decl, builtin_i);
if (builtin != NULL) {
if (icmp(builtin, "length") || icmp(builtin, "low")
|| icmp(builtin, "high") || icmp(builtin, "left")
|| icmp(builtin, "right")) {

type_t type = tree_type(tree_value(tree_param(t, 1)));
if (type_is_array(type) && !type_is_unconstrained(type)) {
tree_t dim_tree = tree_value(tree_param(t, 0));

int64_t dim;
const bool f = folded_int(dim_tree, &dim);
assert(f);

if ((dim < 1) || (dim > type_dims(type)))
bounds_error(dim_tree, "invalid dimension %"PRIi64" for type %s",
dim, type_pp(type));
}
}
else if (icmp(builtin, "event") || icmp(builtin, "active"))
return t;
}

for (int i = 0; (i < nparams) && (i < nports); i++) {
tree_t param = tree_param(t, i);
assert(tree_subkind(param) == P_POS);
Expand Down Expand Up @@ -825,6 +800,37 @@ static void bounds_check_type_conv(tree_t t)
}
}

static void bounds_check_attr_ref(tree_t t)
{
const predef_attr_t predef = tree_attr_int(t, builtin_i, -1);
switch (predef) {
case ATTR_LENGTH:
case ATTR_LOW:
case ATTR_HIGH:
case ATTR_LEFT:
case ATTR_RIGHT:
if (tree_params(t) > 0)
{
type_t type = tree_type(tree_name(t));
if (type_is_array(type) && !type_is_unconstrained(type)) {
tree_t dim_tree = tree_value(tree_param(t, 0));

int64_t dim;
const bool f = folded_int(dim_tree, &dim);
assert(f);

if (dim < 1 || dim > type_dims(type))
bounds_error(dim_tree, "invalid dimension %"PRIi64" for type %s",
dim, type_pp(type));
}
}
break;

default:
break;
}
}

static void bounds_visit_fn(tree_t t, void *context)
{
switch (tree_kind(t)) {
Expand Down Expand Up @@ -861,6 +867,9 @@ static void bounds_visit_fn(tree_t t, void *context)
case T_TYPE_CONV:
bounds_check_type_conv(t);
break;
case T_ATTR_REF:
bounds_check_attr_ref(t);
break;
default:
break;
}
Expand Down
37 changes: 37 additions & 0 deletions src/common.c
Expand Up @@ -229,6 +229,43 @@ bool folded_bool(tree_t t, bool *b)
return false;
}

tree_t get_bool_lit(tree_t t, bool v)
{
type_t bool_type = NULL;
if (!tree_has_type(t)) {
printf("XXX: doing get_bool_lit hack\n");
fmt_loc(stdout, tree_loc(t));

if (bool_type == NULL) {
lib_t std = lib_find("std", true, true);
assert(std != NULL);

tree_t standard = lib_get(std, ident_new("STD.STANDARD"));
assert(standard != NULL);

const int ndecls = tree_decls(standard);
for (int i = 0; (i < ndecls) && (bool_type == NULL); i++) {
tree_t d = tree_decl(standard, i);
if (tree_ident(d) == std_bool_i)
bool_type = tree_type(d);
}
assert(bool_type != NULL);
}
}
else
bool_type = tree_type(t);

tree_t lit = type_enum_literal(bool_type, v ? 1 : 0);

tree_t b = tree_new(T_REF);
tree_set_loc(b, tree_loc(t));
tree_set_ref(b, lit);
tree_set_type(b, bool_type);
tree_set_ident(b, tree_ident(lit));

return b;
}

tree_t get_int_lit(tree_t t, int64_t i)
{
tree_t f = tree_new(T_LITERAL);
Expand Down
9 changes: 8 additions & 1 deletion src/common.h
Expand Up @@ -34,6 +34,7 @@ bool folded_length(range_t r, int64_t *l);
bool folded_enum(tree_t t, unsigned *pos);
bool folded_bounds(range_t r, int64_t *low, int64_t *high);
tree_t get_int_lit(tree_t t, int64_t i);
tree_t get_bool_lit(tree_t t, bool v);
tree_t get_real_lit(tree_t t, double r);
const char *package_signal_path_name(ident_t i);
bool parse_value(type_t type, const char *str, int64_t *value);
Expand Down Expand Up @@ -99,7 +100,13 @@ typedef enum {
ATTR_DELAYED,
ATTR_STABLE,
ATTR_QUIET,
ATTR_TRANSACTION
ATTR_TRANSACTION,
ATTR_LENGTH,
ATTR_LEFT,
ATTR_LOW,
ATTR_HIGH,
ATTR_RIGHT,
ATTR_ASCENDING
} predef_attr_t;

//
Expand Down
81 changes: 0 additions & 81 deletions src/eval.c
Expand Up @@ -125,39 +125,6 @@ static bool folded(tree_t t)
return false;
}

static tree_t get_bool_lit(tree_t t, bool v)
{
tree_t fdecl = tree_ref(t);
assert(tree_kind(fdecl) == T_FUNC_DECL);

static type_t bool_type = NULL;
if (bool_type == NULL) {
lib_t std = lib_find("std", true, true);
assert(std != NULL);

tree_t standard = lib_get(std, ident_new("STD.STANDARD"));
assert(standard != NULL);

const int ndecls = tree_decls(standard);
for (int i = 0; (i < ndecls) && (bool_type == NULL); i++) {
tree_t d = tree_decl(standard, i);
if (tree_ident(d) == std_bool_i)
bool_type = tree_type(d);
}
assert(bool_type != NULL);
}

tree_t lit = type_enum_literal(bool_type, v ? 1 : 0);

tree_t b = tree_new(T_REF);
tree_set_loc(b, tree_loc(t));
tree_set_ref(b, lit);
tree_set_type(b, bool_type);
tree_set_ident(b, tree_ident(lit));

return b;
}

static tree_t eval_fcall_log(tree_t t, ident_t builtin, bool *args)
{
if (icmp(builtin, "not"))
Expand Down Expand Up @@ -378,54 +345,6 @@ static tree_t eval_fcall(tree_t t, vtable_t *v)
return ((result != NULL) && folded(result)) ? result : t;
}

if (icmp(builtin, "length") || icmp(builtin, "low") || icmp(builtin, "high")
|| icmp(builtin, "left") || icmp(builtin, "right")
|| icmp(builtin, "ascending")) {
tree_t dim = tree_value(tree_param(t, 0));
tree_t array = tree_value(tree_param(t, 1));

if (tree_kind(array) != T_REF)
return t; // Cannot fold this

int64_t dim_i;
const bool f = folded_int(dim, &dim_i);
assert(f);

type_t type = tree_type(array);
if (type_is_unconstrained(type))
return t;

if ((dim_i < 1) || (dim_i > type_dims(type)))
return t;

range_t r = type_dim(type, dim_i - 1);

const bool known_dir = (r.kind == RANGE_TO) || (r.kind == RANGE_DOWNTO);

if (icmp(builtin, "length") && known_dir) {
if ((tree_kind(r.left) == T_LITERAL)
&& (tree_kind(r.right) == T_LITERAL)) {
int64_t low, high;
range_bounds(r, &low, &high);
return get_int_lit(t, (high < low) ? 0 : high - low + 1);
}
else
return t;
}
else if (icmp(builtin, "low") && known_dir)
return eval_expr((r.kind == RANGE_TO) ? r.left : r.right, v);
else if (icmp(builtin, "high") && known_dir)
return eval_expr((r.kind == RANGE_TO) ? r.right : r.left, v);
else if (icmp(builtin, "left"))
return eval_expr(r.left, v);
else if (icmp(builtin, "right"))
return eval_expr(r.right, v);
else if (icmp(builtin, "ascending") && known_dir)
return get_bool_lit(t, (r.kind == RANGE_TO));
else
return t;
}

const int nparams = tree_params(t);

tree_t targs[nparams];
Expand Down

0 comments on commit 73f188f

Please sign in to comment.