Skip to content

Commit

Permalink
Remove builtin functions for 'SUCC, 'PRED, etc.
Browse files Browse the repository at this point in the history
  • Loading branch information
nickg committed Apr 19, 2015
1 parent 1eadaf7 commit 41d846b
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 117 deletions.
6 changes: 5 additions & 1 deletion src/common.h
Expand Up @@ -111,7 +111,11 @@ typedef enum {
ATTR_LAST_ACTIVE,
ATTR_DRIVING,
ATTR_DRIVING_VALUE,
ATTR_VALUE
ATTR_VALUE,
ATTR_SUCC,
ATTR_PRED,
ATTR_LEFTOF,
ATTR_RIGHTOF
} predef_attr_t;

//
Expand Down
4 changes: 0 additions & 4 deletions src/eval.c
Expand Up @@ -222,10 +222,6 @@ static tree_t eval_fcall_int(tree_t t, ident_t builtin, int64_t *args, int n)

return get_int_lit(t, result);
}
else if (icmp(builtin, "succ"))
return get_int_lit(t, args[0] + 1);
else if (icmp(builtin, "pred"))
return get_int_lit(t, args[0] - 1);
else if (icmp(builtin, "min")) {
assert(n > 0);
int64_t r = args[0];
Expand Down
48 changes: 34 additions & 14 deletions src/lower.c
Expand Up @@ -1106,20 +1106,6 @@ static vcode_reg_t lower_builtin(tree_t fcall, ident_t builtin)
return emit_not(lower_array_cmp(r0, r1, r0_type, r1_type, VCODE_CMP_LEQ));
else if (icmp(builtin, "ageq"))
return emit_not(lower_array_cmp(r0, r1, r0_type, r1_type, VCODE_CMP_LT));
else if (icmp(builtin, "succ"))
return emit_add(r0, emit_const(vcode_reg_type(r0), 1));
else if (icmp(builtin, "pred"))
return emit_sub(r0, emit_const(vcode_reg_type(r0), 1));
else if (icmp(builtin, "leftof")) {
range_t r = type_dim(tree_type(fcall), 0);
const int dir = (r.kind == RANGE_TO ? -1 : 1);
return emit_add(r0, emit_const(vcode_reg_type(r0), dir));
}
else if (icmp(builtin, "rightof")) {
range_t r = type_dim(tree_type(fcall), 0);
const int dir = (r.kind == RANGE_TO ? 1 : -1);;
return emit_add(r0, emit_const(vcode_reg_type(r0), dir));
}
else if (icmp(builtin, "req"))
return lower_logical(fcall, lower_record_eq(r0, r1, r0_type));
else if (icmp(builtin, "rneq"))
Expand Down Expand Up @@ -2546,6 +2532,40 @@ static vcode_reg_t lower_attr_ref(tree_t expr, expr_ctx_t ctx)
return emit_cast(lower_type(name_type), lower_bounds(name_type), reg);
}

case ATTR_SUCC:
{
tree_t value = tree_value(tree_param(expr, 0));
vcode_reg_t arg = lower_param(value, NULL, PORT_IN);
return emit_add(arg, emit_const(vcode_reg_type(arg), 1));
}

case ATTR_PRED:
{
tree_t value = tree_value(tree_param(expr, 0));
vcode_reg_t arg = lower_param(value, NULL, PORT_IN);
return emit_sub(arg, emit_const(vcode_reg_type(arg), 1));
}

case ATTR_LEFTOF:
{
tree_t value = tree_value(tree_param(expr, 0));
vcode_reg_t arg = lower_param(value, NULL, PORT_IN);

range_t r = type_dim(tree_type(expr), 0);
const int dir = (r.kind == RANGE_TO ? -1 : 1);
return emit_add(arg, emit_const(vcode_reg_type(arg), dir));
}

case ATTR_RIGHTOF:
{
tree_t value = tree_value(tree_param(expr, 0));
vcode_reg_t arg = lower_param(value, NULL, PORT_IN);

range_t r = type_dim(tree_type(expr), 0);
const int dir = (r.kind == RANGE_TO ? 1 : -1);
return emit_add(arg, emit_const(vcode_reg_type(arg), dir));
}

default:
fatal("cannot lower attribute %s", istr(tree_ident(expr)));
}
Expand Down
108 changes: 56 additions & 52 deletions src/sem.c
Expand Up @@ -873,57 +873,11 @@ static void sem_declare_predefined_ops(tree_t decl)

// Predefined attributes

switch (kind) {
case T_ENUM:
{
tree_t left = type_enum_literal(t, 0);
tree_t right = type_enum_literal(t, type_enum_literals(t) - 1);
tree_add_attr_tree(decl, ident_new("LEFT"), make_ref(left));
tree_add_attr_tree(decl, ident_new("RIGHT"), make_ref(right));
tree_add_attr_tree(decl, ident_new("LOW"), make_ref(left));
tree_add_attr_tree(decl, ident_new("HIGH"), make_ref(right));

tree_t image = sem_builtin_fn(ident_new("IMAGE"),
std_string, "image", t, t, NULL);
tree_add_attr_tree(decl, ident_new("IMAGE"), image);

ident_t pos_i = ident_new("POS");
tree_add_attr_tree(decl, pos_i,
sem_builtin_fn(pos_i, std_int, "pos", t, t, NULL));

ident_t val_i = ident_new("VAL");
tree_add_attr_tree(decl, val_i,
sem_builtin_fn(val_i, t, "val",
type_universal_int(), t, NULL));
}
break;

default:
break;
}

switch (type_kind(type_base_recur(t))) {
case T_INTEGER:
case T_PHYSICAL:
case T_ENUM:
{
ident_t succ_i = ident_new("SUCC");
tree_add_attr_tree(decl, succ_i,
sem_builtin_fn(succ_i, t, "succ", t, t, NULL));

ident_t pred_i = ident_new("PRED");
tree_add_attr_tree(decl, pred_i,
sem_builtin_fn(pred_i, t, "pred", t, t, NULL));

ident_t leftof_i = ident_new("LEFTOF");
tree_add_attr_tree(decl, leftof_i,
sem_builtin_fn(leftof_i, t, "leftof", t, t, NULL));

ident_t rightof_i = ident_new("RIGHTOF");
tree_add_attr_tree(decl, rightof_i,
sem_builtin_fn(rightof_i, t, "rightof",
t, t, NULL));

ident_t pos_i = ident_new("POS");
tree_add_attr_tree(decl, pos_i,
sem_builtin_fn(pos_i, std_int, "pos", t, t, NULL));
Expand Down Expand Up @@ -4820,6 +4774,14 @@ static predef_attr_t sem_predefined_attr(ident_t ident)
return ATTR_DRIVING;
else if (icmp(ident, "VALUE"))
return ATTR_VALUE;
else if (icmp(ident, "SUCC"))
return ATTR_SUCC;
else if (icmp(ident, "PRED"))
return ATTR_PRED;
else if (icmp(ident, "LEFTOF"))
return ATTR_LEFTOF;
else if (icmp(ident, "RIGHTOF"))
return ATTR_RIGHTOF;
else
return (predef_attr_t)-1;
}
Expand Down Expand Up @@ -4852,6 +4814,17 @@ static bool sem_check_dimension_attr(tree_t t)
return true;
}

static bool sem_check_attr_param_count(tree_t t, int min, int max)
{
const int nparams = tree_params(t);
if (nparams == 0 && min > 0)
sem_error(t, "attribute %s requires a parameter", istr(tree_ident(t)));
else if (nparams > max)
sem_error(t, "too many parameters for attribute %s", istr(tree_ident(t)));

return true;
}

static bool sem_check_attr_ref(tree_t t)
{
// Attribute names are in LRM 93 section 6.6
Expand Down Expand Up @@ -4952,6 +4925,9 @@ static bool sem_check_attr_ref(tree_t t)
}

case ATTR_LAST_EVENT:
if (!sem_check_attr_param_count(t, 0, 0))
return false;

if (!sem_check_signal_attr(t))
return false;

Expand Down Expand Up @@ -4984,6 +4960,7 @@ static bool sem_check_attr_ref(tree_t t)
tree_set_type(t, sem_std_type("STRING"));
return true;
}

case ATTR_DELAYED:
case ATTR_STABLE:
case ATTR_QUIET:
Expand Down Expand Up @@ -5028,19 +5005,16 @@ static bool sem_check_attr_ref(tree_t t)
case ATTR_IMAGE:
case ATTR_VALUE:
{
if (tree_kind(decl) != T_TYPE_DECL)
if (decl == NULL || tree_kind(decl) != T_TYPE_DECL)
sem_error(t, "prefix of attribute %s must be a type", istr(attr));

type_t name_type = tree_type(name);
if (!type_is_scalar(name_type))
sem_error(t, "cannot use attribute %s with non-scalar type %s",
sem_type_str(name_type), istr(attr));

const int nparams = tree_params(t);
if (nparams == 0)
sem_error(t, "attribute %s requires a parameter", istr(attr));
else if (nparams > 1)
sem_error(t, "too many parameters for attribute %s", istr(attr));
if (!sem_check_attr_param_count(t, 1, 1))
return false;

type_t std_string = sem_std_type("STRING");
type_t arg_type = predef == ATTR_IMAGE ? name_type : std_string;
Expand All @@ -5058,6 +5032,36 @@ static bool sem_check_attr_ref(tree_t t)
return true;
}

case ATTR_LEFTOF:
case ATTR_RIGHTOF:
case ATTR_PRED:
case ATTR_SUCC:
{
if (decl == NULL || tree_kind(decl) != T_TYPE_DECL)
sem_error(t, "prefix of attribute %s must be a type", istr(attr));

type_t name_type = tree_type(name);
if (!type_is_integer(name_type) && !type_is_enum(name_type)
&& !type_is_physical(name_type))
sem_error(t, "prefix of attribute %s must be a discrete or "
"physical type", istr(attr));

if (!sem_check_attr_param_count(t, 1, 1))
return false;

tree_t value = tree_value(tree_param(t, 0));
if (!sem_check_constrained(value, name_type))
return false;

if (!type_eq(tree_type(value), name_type))
sem_error(t, "expected type %s for attribute %s parameter but "
"have %s", sem_type_str(name_type), istr(attr),
sem_type_str(tree_type(value)));

tree_set_type(t, name_type);
return true;
}

case ATTR_DRIVING_VALUE:
case ATTR_LAST_ACTIVE:
case ATTR_DRIVING:
Expand Down
70 changes: 24 additions & 46 deletions src/type.c
Expand Up @@ -616,49 +616,39 @@ const char *type_pp(type_t t)
return type_pp_minify(t, type_minify_identity);
}

bool type_is_array(type_t t)
static type_kind_t type_base_kind(type_t t)
{
assert(t != NULL);
if (t->object.kind == T_SUBTYPE)
return type_is_array(type_base(t));
return type_base_kind(type_base(t));
else
return (t->object.kind == T_CARRAY || t->object.kind == T_UARRAY);
return t->object.kind;
}

bool type_is_array(type_t t)
{
const type_kind_t base = type_base_kind(t);
return base == T_CARRAY || base == T_UARRAY;
}

bool type_is_record(type_t t)
{
assert(t != NULL);
if (t->object.kind == T_SUBTYPE)
return type_is_record(type_base(t));
else
return (t->object.kind == T_RECORD);
return type_base_kind(t) == T_RECORD;
}

bool type_is_protected(type_t t)
{
assert(t != NULL);
if (t->object.kind == T_SUBTYPE)
return type_is_protected(type_base(t));
else
return (t->object.kind == T_PROTECTED);
return type_base_kind(t) == T_PROTECTED;
}

bool type_is_file(type_t t)
{
assert(t != NULL);
if (t->object.kind == T_SUBTYPE)
return type_is_file(type_base(t));
else
return (t->object.kind == T_FILE);
return type_base_kind(t) == T_FILE;
}

bool type_is_access(type_t t)
{
assert(t != NULL);
if (t->object.kind == T_SUBTYPE)
return type_is_access(type_base(t));
else
return (t->object.kind == T_ACCESS);
return type_base_kind(t) == T_ACCESS;
}

bool type_is_unconstrained(type_t t)
Expand All @@ -676,41 +666,29 @@ bool type_is_unconstrained(type_t t)

bool type_is_enum(type_t t)
{
assert(t != NULL);
if (t->object.kind == T_SUBTYPE)
return type_is_enum(type_base(t));
else
return (t->object.kind == T_ENUM);
return type_base_kind(t) == T_ENUM;
}

bool type_is_physical(type_t t)
{
return type_base_kind(t) == T_PHYSICAL;
}

bool type_is_integer(type_t t)
{
assert(t != NULL);
if (t->object.kind == T_SUBTYPE)
return type_is_integer(type_base(t));
else
return (t->object.kind == T_INTEGER);
return type_base_kind(t) == T_INTEGER;
}

bool type_is_real(type_t t)
{
assert(t != NULL);
if (t->object.kind == T_SUBTYPE)
return type_is_real(type_base(t));
else
return (t->object.kind == T_REAL);
return type_base_kind(t) == T_REAL;
}

bool type_is_scalar(type_t t)
{
assert(t != NULL);
if (t->object.kind == T_SUBTYPE)
return type_is_scalar(type_base(t));
else
return (t->object.kind == T_INTEGER)
|| (t->object.kind == T_REAL)
|| (t->object.kind == T_ENUM)
|| (t->object.kind == T_PHYSICAL);
const type_kind_t base = type_base_kind(t);
return base == T_INTEGER || base == T_REAL
|| base == T_ENUM || base == T_PHYSICAL;
}

type_t type_base_recur(type_t t)
Expand Down
1 change: 1 addition & 0 deletions src/type.h
Expand Up @@ -137,6 +137,7 @@ bool type_is_scalar(type_t t);
bool type_is_file(type_t t);
bool type_is_protected(type_t t);
bool type_is_access(type_t t);
bool type_is_physical(type_t t);

// Helper to find ultimate base type
type_t type_base_recur(type_t t);
Expand Down

0 comments on commit 41d846b

Please sign in to comment.