Skip to content

Commit

Permalink
spec: get rid of all specifier MOD_XXX
Browse files Browse the repository at this point in the history
Modifiers like MOD_CHAR, MOD_LONG, ... are used to keep track
of the size/rank of integers and floats. But this is problematic:
* they use 5 of the precious modifiers bits
* they're not really modifiers but the base of the primitive types
* a 'long double' has MOD_LONGLONG set

Change this by using instead the explicit notion of 'rank'.
The advanatges are:
* using only 3 bits (in struct symbol)
* free 5 modifier bits
* follow closely the definition & rules of the standard
* things like integer promotion are slightly simpler.

Note: this is somewhat experimental as I'm not yet convinced
      that everything is correct (but the testsuite is OK
      and gives the same result for a defconfig + allyesconfig
      build of the kernel).

Signed-off-by: Luc Van Oostenryck <[email protected]>
  • Loading branch information
lucvoo committed Nov 25, 2019
1 parent 3d51513 commit 10b89d6
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 95 deletions.
19 changes: 8 additions & 11 deletions evaluate.c
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ static inline struct symbol *integer_promotion(struct symbol *type)
return &int_ctype;

/* If char/short has as many bits as int, it still gets "promoted" */
if (mod & (MOD_CHAR | MOD_SHORT)) {
if (type->rank < 0) {
if (mod & MOD_UNSIGNED)
return &uint_ctype;
return &int_ctype;
Expand Down Expand Up @@ -196,7 +196,7 @@ static struct symbol *bigger_int_type(struct symbol *left, struct symbol *right)
if ((lmod ^ rmod) & MOD_UNSIGNED) {
if (lmod & MOD_UNSIGNED)
goto left;
} else if ((lmod & ~rmod) & (MOD_LONG_ALL))
} else if (left->rank > right->rank)
goto left;
right:
left = right;
Expand Down Expand Up @@ -557,9 +557,7 @@ static struct symbol *usual_conversions(int op,
else
return rtype;
} else if (rclass & TYPE_FLOAT) {
unsigned long lmod = ltype->ctype.modifiers;
unsigned long rmod = rtype->ctype.modifiers;
if (rmod & ~lmod & (MOD_LONG_ALL))
if (rtype->rank > ltype->rank)
return rtype;
else
return ltype;
Expand Down Expand Up @@ -798,11 +796,11 @@ const char *type_difference(struct ctype *c1, struct ctype *c2,
return "different address spaces";
if (base1 != base2)
return "different base types";
if (t1->rank != t2->rank)
return "different type sizes";
diff = (mod1 ^ mod2) & ~MOD_IGNORE;
if (!diff)
return NULL;
if (diff & MOD_SIZE)
return "different type sizes";
else if (diff & ~MOD_SIGNEDNESS)
return "different modifiers";
else
Expand Down Expand Up @@ -1391,9 +1389,9 @@ static int whitelist_pointers(struct symbol *t1, struct symbol *t2)
return 0;
if (t1 == t2)
return 1;
if (t1->ctype.modifiers & t2->ctype.modifiers & MOD_CHAR)
if (t1->rank == -2 && t2->rank == -2)
return 1;
if ((t1->ctype.modifiers ^ t2->ctype.modifiers) & MOD_SIZE)
if (t1->rank != t2->rank)
return 0;
return !Wtypesign;
}
Expand Down Expand Up @@ -2344,8 +2342,7 @@ static int evaluate_arguments(struct symbol *fn, struct expression_list *head)
if (is_int(class)) {
*p = cast_to(expr, integer_promotion(type));
} else if (class & TYPE_FLOAT) {
unsigned long mod = type->ctype.modifiers;
if (!(mod & (MOD_LONG_ALL)))
if (type->rank < 0)
*p = cast_to(expr, &double_ctype);
} else if (class & TYPE_PTR) {
if (expr->ctype == &null_ctype)
Expand Down
11 changes: 5 additions & 6 deletions expand.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,8 @@ void cast_value(struct expression *expr, struct symbol *newtype,
else
expr->fvalue = old->fvalue;

if (!(newtype->ctype.modifiers & MOD_LONGLONG) && \
!(newtype->ctype.modifiers & MOD_LONGLONGLONG)) {
if ((newtype->ctype.modifiers & MOD_LONG))
if (newtype->rank <= 0) {
if (newtype->rank == 0)
expr->fvalue = (double)expr->fvalue;
else
expr->fvalue = (float)expr->fvalue;
Expand Down Expand Up @@ -358,7 +357,7 @@ static int simplify_cmp_binop(struct expression *expr, struct symbol *ctype)
static int simplify_float_binop(struct expression *expr)
{
struct expression *left = expr->left, *right = expr->right;
unsigned long mod = expr->ctype->ctype.modifiers;
int rank = expr->ctype->rank;
long double l, r, res;

if (left->type != EXPR_FVALUE || right->type != EXPR_FVALUE)
Expand All @@ -367,7 +366,7 @@ static int simplify_float_binop(struct expression *expr)
l = left->fvalue;
r = right->fvalue;

if (mod & MOD_LONGLONG) {
if (rank > 0) {
switch (expr->op) {
case '+': res = l + r; break;
case '-': res = l - r; break;
Expand All @@ -376,7 +375,7 @@ static int simplify_float_binop(struct expression *expr)
res = l / r; break;
default: return 0;
}
} else if (mod & MOD_LONG) {
} else if (rank == 0) {
switch (expr->op) {
case '+': res = (double) l + (double) r; break;
case '-': res = (double) l - (double) r; break;
Expand Down
15 changes: 0 additions & 15 deletions gdbhelpers
Original file line number Diff line number Diff line change
Expand Up @@ -119,21 +119,6 @@ define gdb_show_ctype
if ($arg0->modifiers & MOD_UNSIGNED)
printf "MOD_UNSIGNED "
end
if ($arg0->modifiers & MOD_CHAR)
printf "MOD_CHAR "
end
if ($arg0->modifiers & MOD_SHORT)
printf "MOD_SHORT "
end
if ($arg0->modifiers & MOD_LONG)
printf "MOD_LONG "
end
if ($arg0->modifiers & MOD_LONGLONG)
printf "MOD_LONGLONG "
end
if ($arg0->modifiers & MOD_LONGLONGLONG)
printf "MOD_LONGLONGLONG "
end
if ($arg0->modifiers & MOD_INLINE)
printf "MOD_INLINE "
end
Expand Down
12 changes: 5 additions & 7 deletions parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,6 @@ static struct symbol_op int_op = {
.type = KW_SPECIFIER,
.test = Set_T,
.set = Set_T|Set_Int,
.class = CInt,
};

static struct symbol_op double_op = {
Expand All @@ -276,7 +275,6 @@ static struct symbol_op short_op = {
.type = KW_SPECIFIER,
.test = Set_S|Set_Char|Set_Float|Set_Double|Set_Long|Set_Short,
.set = Set_Short,
.class = CInt,
};

static struct symbol_op signed_op = {
Expand Down Expand Up @@ -1624,12 +1622,12 @@ static struct token *declaration_specifiers(struct token *token, struct decl_sta
}
seen |= s->op->set;
class += s->op->class;
if (s->op->set & Set_Int128)
rank = 3;
else if (s->op->set & Set_Char)
rank = -2;
if (s->op->set & (Set_Short|Set_Float)) {
rank = -1;
} else if (s->op->set & Set_Char) {
rank = -2;
} else if (s->op->set & Set_Int128) {
rank = 3;
} else if (s->op->set & Set_Long && rank++) {
if (class == CReal) {
specifier_conflict(token->pos,
Expand Down Expand Up @@ -2823,7 +2821,7 @@ static struct token *parse_function_body(struct token *token, struct symbol *dec
static void promote_k_r_types(struct symbol *arg)
{
struct symbol *base = arg->ctype.base_type;
if (base && base->ctype.base_type == &int_type && (base->ctype.modifiers & (MOD_CHAR | MOD_SHORT))) {
if (base && base->ctype.base_type == &int_type && base->rank < 0) {
arg->ctype.base_type = &int_ctype;
}
}
Expand Down
5 changes: 0 additions & 5 deletions show-parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,11 +128,6 @@ const char *modifier_string(unsigned long mod)
{MOD_ATOMIC, "[atomic]"},
{MOD_SIGNED, "[signed]"},
{MOD_UNSIGNED, "[unsigned]"},
{MOD_CHAR, "[char]"},
{MOD_SHORT, "[short]"},
{MOD_LONG, "[long]"},
{MOD_LONGLONG, "[long long]"},
{MOD_LONGLONGLONG, "[long long long]"},
{MOD_TLS, "[tls]"},
{MOD_INLINE, "inline"},
{MOD_ADDRESSABLE, "[addressable]"},
Expand Down
85 changes: 42 additions & 43 deletions symbol.c
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ static struct symbol *examine_base_type(struct symbol *sym)
if (base_type->type == SYM_NODE) {
base_type = base_type->ctype.base_type;
sym->ctype.base_type = base_type;
sym->rank = base_type->rank;
}
return base_type;
}
Expand Down Expand Up @@ -299,7 +300,7 @@ static int count_array_initializer(struct symbol *t, struct expression *expr)
* on T - if it's a character type, we get the length of string literal
* (including NUL), otherwise we have one element here.
*/
if (t->ctype.base_type == &int_type && t->ctype.modifiers & MOD_CHAR)
if (t->ctype.base_type == &int_type && t->rank == -2)
is_char = 1;

switch (expr->type) {
Expand Down Expand Up @@ -416,6 +417,7 @@ static struct symbol * examine_node_type(struct symbol *sym)
}

sym->bit_size = bit_size;
sym->rank = base_type->rank;
return sym;
}

Expand Down Expand Up @@ -561,6 +563,7 @@ void create_fouled(struct symbol *type)
struct symbol *new = alloc_symbol(type->pos, type->type);
*new = *type;
new->bit_size = bits_in_int;
new->rank = 0;
new->type = SYM_FOULED;
new->ctype.base_type = type;
add_symbol(&restr, type);
Expand Down Expand Up @@ -730,63 +733,60 @@ static int bits_in_type32 = 32;
static int bits_in_type64 = 64;
static int bits_in_type128 = 128;

#define MOD_ESIGNED (MOD_SIGNED | MOD_EXPLICITLY_SIGNED)
#define MOD_LL (MOD_LONG | MOD_LONGLONG)
#define MOD_LLL MOD_LONGLONGLONG

#define T_BASETYPE SYM_BASETYPE, 0, NULL, NULL, NULL
#define T_INT(R, S, M) SYM_BASETYPE, (R|M), &bits_in_##S, &max_int_alignment, &int_type
#define T_BASETYPE SYM_BASETYPE, 0, 0, NULL, NULL, NULL
#define T_INT(R, S, M) SYM_BASETYPE, M, R, &bits_in_##S, &max_int_alignment, &int_type
#define T__INT(R, S) T_INT(R, S, MOD_SIGNED)
#define T_SINT(R, S) T_INT(R, S, MOD_ESIGNED)
#define T_UINT(R, S) T_INT(R, S, MOD_UNSIGNED)
#define T_FLOAT_(R,S,A) SYM_BASETYPE, R, &bits_in_##S, A, &fp_type
#define T_UINT(R,S) T_INT(R, S, MOD_UNSIGNED)
#define T_FLOAT_(R,S,A) SYM_BASETYPE, 0, R, &bits_in_##S, A, &fp_type
#define T_FLOAT(R, S) T_FLOAT_(R, S, &max_fp_alignment)
#define T_PTR(B) SYM_PTR, 0, &bits_in_pointer, &pointer_alignment, B
#define T_NODE(M,B,S,A) SYM_NODE, M, S, A, B
#define T_PTR(B) SYM_PTR, 0, 0, &bits_in_pointer, &pointer_alignment, B
#define T_NODE(M,B,S,A) SYM_NODE, M, 0, S, A, B
#define T_CONST(B,S,A) T_NODE(MOD_CONST, B, S, A)

static const struct ctype_declare {
struct symbol *ptr;
enum type type;
unsigned long modifiers;
int rank;
int *bit_size;
int *maxalign;
struct symbol *base_type;
} ctype_declaration[] = {
{ &bool_ctype, T_INT(0, bool, MOD_UNSIGNED) },
{ &bool_ctype, T_INT(-3, bool, MOD_UNSIGNED) },
{ &void_ctype, T_BASETYPE },
{ &type_ctype, T_BASETYPE },
{ &incomplete_ctype, T_BASETYPE },
{ &bad_ctype, T_BASETYPE },

{ &char_ctype, T__INT(MOD_CHAR, char) },
{ &schar_ctype, T_SINT(MOD_CHAR, char) },
{ &uchar_ctype, T_UINT(MOD_CHAR, char) },
{ &short_ctype, T__INT(MOD_SHORT, short) },
{ &sshort_ctype, T_SINT(MOD_SHORT, short) },
{ &ushort_ctype, T_UINT(MOD_SHORT, short) },
{ &int_ctype, T__INT(0, int) },
{ &sint_ctype, T_SINT(0, int) },
{ &uint_ctype, T_UINT(0, int) },
{ &long_ctype, T__INT(MOD_LONG, long) },
{ &slong_ctype, T_SINT(MOD_LONG, long) },
{ &ulong_ctype, T_UINT(MOD_LONG, long) },
{ &llong_ctype, T__INT(MOD_LL, longlong) },
{ &sllong_ctype, T_SINT(MOD_LL, longlong) },
{ &ullong_ctype, T_UINT(MOD_LL, longlong) },
{ &lllong_ctype, T__INT(MOD_LLL, longlonglong) },
{ &slllong_ctype, T_SINT(MOD_LLL, longlonglong) },
{ &ulllong_ctype, T_UINT(MOD_LLL, longlonglong) },

{ &float_ctype, T_FLOAT(0, float) },
{ &double_ctype, T_FLOAT(MOD_LONG, double) },
{ &ldouble_ctype, T_FLOAT(MOD_LL, longdouble) },

{ &float32_ctype, T_FLOAT(0, type32) },
{ &float32x_ctype, T_FLOAT(MOD_LONG, double) },
{ &float64_ctype, T_FLOAT(MOD_LONG, type64) },
{ &float64x_ctype, T_FLOAT(MOD_LONG, longdouble) },
{ &float128_ctype, T_FLOAT_(MOD_LL, type128, &max_alignment) },
{ &char_ctype, T__INT(-2, char) },
{ &schar_ctype, T_SINT(-2, char) },
{ &uchar_ctype, T_UINT(-2, char) },
{ &short_ctype, T__INT(-1, short) },
{ &sshort_ctype, T_SINT(-1, short) },
{ &ushort_ctype, T_UINT(-1, short) },
{ &int_ctype, T__INT( 0, int) },
{ &sint_ctype, T_SINT( 0, int) },
{ &uint_ctype, T_UINT( 0, int) },
{ &long_ctype, T__INT( 1, long) },
{ &slong_ctype, T_SINT( 1, long) },
{ &ulong_ctype, T_UINT( 1, long) },
{ &llong_ctype, T__INT( 2, longlong) },
{ &sllong_ctype, T_SINT( 2, longlong) },
{ &ullong_ctype, T_UINT( 2, longlong) },
{ &lllong_ctype, T__INT( 3, longlonglong) },
{ &slllong_ctype, T_SINT( 3, longlonglong) },
{ &ulllong_ctype, T_UINT( 3, longlonglong) },

{ &float_ctype, T_FLOAT(-1, float) },
{ &double_ctype, T_FLOAT( 0, double) },
{ &ldouble_ctype, T_FLOAT( 1, longdouble) },

{ &float32_ctype, T_FLOAT(-1, type32) },
{ &float32x_ctype, T_FLOAT(-1, double) },
{ &float64_ctype, T_FLOAT( 0, type64) },
{ &float64x_ctype, T_FLOAT( 1, longdouble) },
{ &float128_ctype, T_FLOAT_(2, type128, &max_alignment) },

{ &string_ctype, T_PTR(&char_ctype) },
{ &ptr_ctype, T_PTR(&void_ctype) },
Expand All @@ -806,9 +806,6 @@ static const struct ctype_declare {
{ &const_char_ctype, T_CONST(&char_ctype, &bits_in_char, &max_int_alignment)},
{ NULL, }
};
#undef MOD_LLL
#undef MOD_LL
#undef MOD_ESIGNED

void init_ctype(void)
{
Expand All @@ -823,13 +820,15 @@ void init_ctype(void)
if (alignment > maxalign)
alignment = maxalign;
sym->type = ctype->type;
sym->rank = ctype->rank;
sym->bit_size = bit_size;
sym->ctype.alignment = alignment;
sym->ctype.base_type = ctype->base_type;
sym->ctype.modifiers = ctype->modifiers;

if (sym->type == SYM_NODE) {
struct symbol *base = sym->ctype.base_type;
sym->rank = base->rank;
if (!ctype->bit_size)
sym->bit_size = base->bit_size;
if (!ctype->maxalign)
Expand Down
16 changes: 8 additions & 8 deletions symbol.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ struct symbol {
builtin:1,
torename:1,
transparent_union:1;
int rank:3; // arithmetic's rank
struct expression *array_size;
struct ctype ctype;
struct symbol_list *arguments;
Expand Down Expand Up @@ -224,11 +225,11 @@ struct symbol {

// MOD UNUSED 0x00010000
#define MOD_USERTYPE 0x00020000
#define MOD_CHAR 0x00040000
#define MOD_SHORT 0x00080000
#define MOD_LONG 0x00100000
#define MOD_LONGLONG 0x00200000
#define MOD_LONGLONGLONG 0x00400000
// MOD UNUSED 0x00040000
// MOD UNUSED 0x00080000
// MOD UNUSED 0x00100000
// MOD UNUSED 0x00200000
// MOD UNUSED 0x00400000

#define MOD_SAFE 0x00800000 // non-null/non-trapping pointer
#define MOD_PURE 0x01000000
Expand All @@ -242,10 +243,9 @@ struct symbol {
#define MOD_ACCESS (MOD_ASSIGNED | MOD_ADDRESSABLE)
#define MOD_NONLOCAL (MOD_EXTERN | MOD_TOPLEVEL)
#define MOD_STORAGE (MOD_AUTO | MOD_REGISTER | MOD_STATIC | MOD_EXTERN | MOD_INLINE | MOD_TOPLEVEL)
#define MOD_ESIGNED (MOD_SIGNED | MOD_EXPLICITLY_SIGNED)
#define MOD_SIGNEDNESS (MOD_SIGNED | MOD_UNSIGNED | MOD_EXPLICITLY_SIGNED)
#define MOD_LONG_ALL (MOD_LONG | MOD_LONGLONG | MOD_LONGLONGLONG)
#define MOD_SPECIFIER (MOD_CHAR | MOD_SHORT | MOD_LONG_ALL | MOD_SIGNEDNESS)
#define MOD_SIZE (MOD_CHAR | MOD_SHORT | MOD_LONG_ALL)
#define MOD_SPECIFIER MOD_SIGNEDNESS
#define MOD_IGNORE (MOD_STORAGE | MOD_ACCESS | MOD_USERTYPE | MOD_EXPLICITLY_SIGNED | MOD_EXT_VISIBLE)
#define MOD_QUALIFIER (MOD_CONST | MOD_VOLATILE | MOD_RESTRICT | MOD_ATOMIC)
#define MOD_PTRINHERIT (MOD_QUALIFIER | MOD_NODEREF | MOD_NORETURN | MOD_NOCAST)
Expand Down

0 comments on commit 10b89d6

Please sign in to comment.