aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
authorAlexander Viro <viro@www.linux.org.uk>2004-07-23 22:35:46 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-07 21:02:18 -0700
commit9c2ebe3f27f19095e2822463aa713be4b8b523d2 (patch)
tree8fc6a25bc864b026da78824d9c961e8536f06084
parent07bc6f3abd6f1b16d3b7476a84aa127b56bb1233 (diff)
downloadsparse-dev-9c2ebe3f27f19095e2822463aa713be4b8b523d2.tar.gz
[PATCH] FP handling
FP handling added, everything straightforward by now.
-rw-r--r--evaluate.c138
-rw-r--r--expand.c198
-rw-r--r--expression.c40
-rw-r--r--expression.h4
-rw-r--r--inline.c1
-rw-r--r--linearize.c11
-rw-r--r--show-parse.c11
-rw-r--r--symbol.c2
8 files changed, 326 insertions, 79 deletions
diff --git a/evaluate.c b/evaluate.c
index 990a5957..02cbca84 100644
--- a/evaluate.c
+++ b/evaluate.c
@@ -203,12 +203,55 @@ static inline int is_int_type(struct symbol *type)
type->ctype.base_type == &int_type;
}
+static inline int is_float_type(struct symbol *type)
+{
+ if (type->type == SYM_NODE)
+ type = type->ctype.base_type;
+ return type->ctype.base_type == &fp_type;
+}
+
static struct symbol *bad_expr_type(struct expression *expr)
{
warn(expr->pos, "incompatible types for operation");
return NULL;
}
+static struct symbol *compatible_float_binop(struct expression **lp, struct expression **rp)
+{
+ struct expression *left = *lp, *right = *rp;
+ struct symbol *ltype = left->ctype, *rtype = right->ctype;
+
+ if (ltype->type == SYM_NODE)
+ ltype = ltype->ctype.base_type;
+ if (rtype->type == SYM_NODE)
+ rtype = rtype->ctype.base_type;
+ if (is_float_type(ltype)) {
+ if (is_int_type(rtype))
+ goto Left;
+ if (is_float_type(rtype)) {
+ unsigned long lmod = ltype->ctype.modifiers;
+ unsigned long rmod = rtype->ctype.modifiers;
+ lmod &= MOD_LONG | MOD_LONGLONG;
+ rmod &= MOD_LONG | MOD_LONGLONG;
+ if (lmod == rmod)
+ return ltype;
+ if (lmod & ~rmod)
+ goto Left;
+ else
+ goto Right;
+ }
+ return NULL;
+ }
+ if (!is_float_type(rtype) || !is_int_type(ltype))
+ return NULL;
+Right:
+ *lp = cast_to(left, rtype);
+ return rtype;
+Left:
+ *rp = cast_to(right, ltype);
+ return ltype;
+}
+
static struct symbol *compatible_integer_binop(struct expression **lp, struct expression **rp)
{
struct expression *left = *lp, *right = *rp;
@@ -234,6 +277,8 @@ static struct symbol *compatible_integer_binop(struct expression **lp, struct ex
static struct symbol *evaluate_arith(struct expression *expr, int float_ok)
{
struct symbol *ctype = compatible_integer_binop(&expr->left, &expr->right);
+ if (!ctype && float_ok)
+ ctype = compatible_float_binop(&expr->left, &expr->right);
if (ctype) {
expr->ctype = ctype;
return ctype;
@@ -313,7 +358,6 @@ static struct symbol *evaluate_add(struct expression *expr)
if (is_ptr_type(rtype))
return evaluate_ptr_add(expr, right, left);
- // FIXME! FP promotion
return evaluate_arith(expr, 1);
}
@@ -545,7 +589,6 @@ static struct symbol *evaluate_sub(struct expression *expr)
if (is_ptr_type(ltype))
return evaluate_ptr_sub(expr, left, right);
- // FIXME! FP promotion
return evaluate_arith(expr, 1);
}
@@ -563,8 +606,29 @@ static struct symbol *evaluate_conditional(struct expression **p)
warn(expr->pos, "assignment expression in conditional");
ctype = evaluate_expression(expr);
- if (ctype && is_safe_type(ctype))
- warn(expr->pos, "testing a 'safe expression'");
+ if (ctype) {
+ if (is_safe_type(ctype))
+ warn(expr->pos, "testing a 'safe expression'");
+ if (is_float_type(ctype)) {
+ struct expression *comp;
+ /*
+ * It's easier to handle here, rather than deal with
+ * FP all over the place. Floating point in boolean
+ * context is rare enough (and very often wrong),
+ * so price of explicit comparison with appropriate
+ * FP zero is not too high. And it simplifies things
+ * elsewhere.
+ */
+ comp = alloc_expression(expr->pos, EXPR_BINOP);
+ comp->op = SPECIAL_NOTEQUAL;
+ comp->left = expr;
+ comp->right = alloc_expression(expr->pos, EXPR_FVALUE);
+ comp->right->ctype = comp->left->ctype;
+ comp->right->fvalue = 0;
+ ctype = comp->ctype = &bool_ctype;
+ *p = comp;
+ }
+ }
return ctype;
}
@@ -676,15 +740,11 @@ static struct symbol *evaluate_compare(struct expression *expr)
expr->ctype = &bool_ctype;
return &bool_ctype;
}
+ ctype = compatible_float_binop(&expr->left, &expr->right);
return bad_expr_type(expr);
}
-static int compatible_integer_types(struct symbol *ltype, struct symbol *rtype)
-{
- return (is_int_type(ltype) && is_int_type(rtype));
-}
-
/*
* FIXME!! This should do casts, array degeneration etc..
*/
@@ -731,17 +791,22 @@ static struct symbol * evaluate_conditional_expression(struct expression *expr)
ctype = ltype;
typediff = type_difference(ltype, rtype, MOD_IGN, MOD_IGN);
- if (typediff) {
- ctype = compatible_integer_binop(&true, &expr->cond_false);
- if (!ctype) {
- ctype = compatible_ptr_type(true, expr->cond_false);
- if (!ctype) {
- warn(expr->pos, "incompatible types in conditional expression (%s)", typediff);
- return NULL;
- }
- }
- }
+ if (!typediff)
+ goto out;
+
+ ctype = compatible_integer_binop(&true, &expr->cond_false);
+ if (ctype)
+ goto out;
+ ctype = compatible_ptr_type(true, expr->cond_false);
+ if (ctype)
+ goto out;
+ ctype = compatible_float_binop(&true, &expr->cond_false);
+ if (ctype)
+ goto out;
+ warn(expr->pos, "incompatible types in conditional expression (%s)", typediff);
+ return NULL;
+out:
expr->ctype = ctype;
return ctype;
}
@@ -758,10 +823,22 @@ static int compatible_assignment_types(struct expression *expr, struct symbol *t
if (!typediff)
return 1;
- if (compatible_integer_types(target, source)) {
- if (target->bit_size != source->bit_size)
- *rp = cast_to(*rp, target);
- return 1;
+ if (is_int_type(target)) {
+ if (is_int_type(source)) {
+ if (target->bit_size != source->bit_size)
+ goto Cast;
+ return 1;
+ }
+ if (is_float_type(source))
+ goto Cast;
+ } else if (is_float_type(target)) {
+ if (is_int_type(source))
+ goto Cast;
+ if (is_float_type(source)) {
+ if (target->bit_size != source->bit_size)
+ goto Cast;
+ return 1;
+ }
}
/* Pointer destination? */
@@ -799,6 +876,9 @@ static int compatible_assignment_types(struct expression *expr, struct symbol *t
info(expr->pos, " expected %s", show_typename(target));
info(expr->pos, " got %s", show_typename(source));
return 0;
+Cast:
+ *rp = cast_to(*rp, target);
+ return 1;
}
/*
@@ -1088,6 +1168,8 @@ static struct symbol *evaluate_sign(struct expression *expr)
if (rtype->bit_size != ctype->bit_size)
expr->unop = cast_to(expr->unop, rtype);
ctype = rtype;
+ } else if (is_float_type(ctype) && expr->op != '%') {
+ /* no conversions needed */
} else {
return bad_expr_type(expr);
}
@@ -1128,6 +1210,15 @@ static struct symbol *evaluate_preop(struct expression *expr)
case '!':
if (is_safe_type(ctype))
warn(expr->pos, "testing a 'safe expression'");
+ if (is_float_type(ctype)) {
+ struct expression *arg = expr->unop;
+ expr->type = EXPR_BINOP;
+ expr->op = SPECIAL_EQUAL;
+ expr->left = arg;
+ expr->right = alloc_expression(expr->pos, EXPR_FVALUE);
+ expr->right->ctype = ctype;
+ expr->right->fvalue = 0;
+ }
ctype = &bool_ctype;
break;
@@ -1660,6 +1751,7 @@ struct symbol *evaluate_expression(struct expression *expr)
switch (expr->type) {
case EXPR_VALUE:
+ case EXPR_FVALUE:
warn(expr->pos, "value expression without a type");
return NULL;
case EXPR_STRING:
diff --git a/expand.c b/expand.c
index 2ab1ee0e..74ba852a 100644
--- a/expand.c
+++ b/expand.c
@@ -43,19 +43,32 @@ static void expand_symbol_expression(struct expression *expr)
}
}
+static long long get_longlong(struct expression *expr)
+{
+ int no_expand = expr->ctype->ctype.modifiers & MOD_UNSIGNED;
+ long long mask = 1ULL << (expr->ctype->bit_size - 1);
+ long long value = expr->value;
+ long long ormask, andmask;
+
+ if (!(value & mask))
+ no_expand = 1;
+ andmask = mask | (mask-1);
+ ormask = ~andmask;
+ if (no_expand)
+ ormask = 0;
+ return (value & andmask) | ormask;
+}
+
void cast_value(struct expression *expr, struct symbol *newtype,
struct expression *old, struct symbol *oldtype)
{
int old_size = oldtype->bit_size;
int new_size = newtype->bit_size;
- long long value, mask, ormask, andmask;
- int is_signed;
+ long long value, mask;
- // FIXME! We don't handle FP casts of constant values yet
- if (newtype->ctype.base_type == &fp_type)
- return;
- if (oldtype->ctype.base_type == &fp_type)
- return;
+ if (newtype->ctype.base_type == &fp_type ||
+ oldtype->ctype.base_type == &fp_type)
+ goto Float;
// For pointers and integers, we can just move the value around
expr->type = EXPR_VALUE;
@@ -65,21 +78,34 @@ void cast_value(struct expression *expr, struct symbol *newtype,
}
// expand it to the full "long long" value
- is_signed = !(oldtype->ctype.modifiers & MOD_UNSIGNED);
- mask = 1ULL << (old_size-1);
- value = old->value;
- if (!(value & mask))
- is_signed = 0;
- andmask = mask | (mask-1);
- ormask = ~andmask;
- if (!is_signed)
- ormask = 0;
- value = (value & andmask) | ormask;
+ value = get_longlong(old);
+Int:
// Truncate it to the new size
mask = 1ULL << (new_size-1);
mask = mask | (mask-1);
expr->value = value & mask;
+ return;
+
+Float:
+ if (newtype->ctype.base_type != &fp_type) {
+ value = (long long)expr->fvalue;
+ expr->type = EXPR_VALUE;
+ goto Int;
+ }
+
+ if (oldtype->ctype.base_type != &fp_type)
+ expr->fvalue = (long double)get_longlong(old);
+ else
+ expr->fvalue = old->value;
+
+ if (!(newtype->ctype.modifiers & MOD_LONGLONG)) {
+ if ((newtype->ctype.modifiers & MOD_LONG))
+ expr->fvalue = (double)expr->fvalue;
+ else
+ expr->fvalue = (float)expr->fvalue;
+ }
+ expr->type = EXPR_FVALUE;
}
static int check_shift_count(struct expression *expr, struct symbol *ctype, unsigned int count)
@@ -95,7 +121,7 @@ static int check_shift_count(struct expression *expr, struct symbol *ctype, unsi
* CAREFUL! We need to get the size and sign of the
* result right!
*/
-static void simplify_int_binop(struct expression *expr, struct symbol *ctype)
+static int simplify_int_binop(struct expression *expr, struct symbol *ctype)
{
struct expression *left = expr->left, *right = expr->right;
unsigned long long v, l, r, mask;
@@ -103,7 +129,7 @@ static void simplify_int_binop(struct expression *expr, struct symbol *ctype)
int is_signed, shift;
if (left->type != EXPR_VALUE || right->type != EXPR_VALUE)
- return;
+ return 0;
l = left->value; r = right->value;
is_signed = !(ctype->ctype.modifiers & MOD_UNSIGNED);
mask = 1ULL << (ctype->bit_size-1);
@@ -120,27 +146,31 @@ static void simplify_int_binop(struct expression *expr, struct symbol *ctype)
case '|': v = l | r; s = v; break;
case '^': v = l ^ r; s = v; break;
case '*': v = l * r; s = sl * sr; break;
- case '/': if (!r) return; v = l / r; s = sl / sr; break;
- case '%': if (!r) return; v = l % r; s = sl % sr; break;
+ case '/': if (!r) goto Div; v = l / r; s = sl / sr; break;
+ case '%': if (!r) goto Div; v = l % r; s = sl % sr; break;
case SPECIAL_LEFTSHIFT: shift = check_shift_count(expr, ctype, r); v = l << shift; s = v; break;
case SPECIAL_RIGHTSHIFT:shift = check_shift_count(expr, ctype, r); v = l >> shift; s = sl >> shift; break;
- default: return;
+ default: return 0;
}
if (is_signed)
v = s;
mask = mask | (mask-1);
expr->value = v & mask;
expr->type = EXPR_VALUE;
+ return 1;
+Div:
+ warn(expr->pos, "division by zero");
+ return 0;
}
-static void simplify_cmp_binop(struct expression *expr, struct symbol *ctype)
+static int simplify_cmp_binop(struct expression *expr, struct symbol *ctype)
{
struct expression *left = expr->left, *right = expr->right;
unsigned long long l, r, mask;
signed long long sl, sr;
if (left->type != EXPR_VALUE || right->type != EXPR_VALUE)
- return;
+ return 0;
l = left->value; r = right->value;
mask = 1ULL << (ctype->bit_size-1);
sl = l; sr = r;
@@ -161,11 +191,80 @@ static void simplify_cmp_binop(struct expression *expr, struct symbol *ctype)
case SPECIAL_UNSIGNED_GTE:expr->value = l >= r; break;
}
expr->type = EXPR_VALUE;
+ return 1;
}
-static void expand_int_binop(struct expression *expr)
+static int simplify_float_binop(struct expression *expr)
{
- simplify_int_binop(expr, expr->ctype);
+ struct expression *left = expr->left, *right = expr->right;
+ unsigned long mod = expr->ctype->ctype.modifiers;
+ long double l = left->fvalue;
+ long double r = right->fvalue;
+ long double res;
+
+ if (left->type != EXPR_FVALUE || right->type != EXPR_FVALUE)
+ return 0;
+ if (mod & MOD_LONGLONG) {
+ switch (expr->op) {
+ case '+': res = l + r; break;
+ case '-': res = l - r; break;
+ case '*': res = l * r; break;
+ case '/': if (!r) goto Div;
+ res = l / r; break;
+ default: return 0;
+ }
+ } else if (mod & MOD_LONG) {
+ switch (expr->op) {
+ case '+': res = (double) l + (double) r; break;
+ case '-': res = (double) l - (double) r; break;
+ case '*': res = (double) l * (double) r; break;
+ case '/': if (!r) goto Div;
+ res = (double) l / (double) r; break;
+ default: return 0;
+ }
+ } else {
+ switch (expr->op) {
+ case '+': res = (float)l + (float)r; break;
+ case '-': res = (float)l - (float)r; break;
+ case '*': res = (float)l * (float)r; break;
+ case '/': if (!r) goto Div;
+ res = (float)l / (float)r; break;
+ default: return 0;
+ }
+ }
+ expr->type = EXPR_FVALUE;
+ expr->fvalue = res;
+ return 1;
+Div:
+ warn(expr->pos, "division by zero");
+ return 0;
+}
+
+static int simplify_float_cmp(struct expression *expr, struct symbol *ctype)
+{
+ struct expression *left = expr->left, *right = expr->right;
+ long double l = left->fvalue, r = right->fvalue;
+
+ if (left->type != EXPR_FVALUE || right->type != EXPR_FVALUE)
+ return 0;
+
+ switch (expr->op) {
+ case '<': expr->value = l < r; break;
+ case '>': expr->value = l > r; break;
+ case SPECIAL_LTE: expr->value = l <= r; break;
+ case SPECIAL_GTE: expr->value = l >= r; break;
+ case SPECIAL_EQUAL: expr->value = l == r; break;
+ case SPECIAL_NOTEQUAL: expr->value = l != r; break;
+ }
+ expr->type = EXPR_VALUE;
+ return 1;
+}
+
+static void expand_binop(struct expression *expr)
+{
+ if (simplify_int_binop(expr, expr->ctype))
+ return;
+ simplify_float_binop(expr);
}
static void expand_logical(struct expression *expr)
@@ -203,14 +302,9 @@ static void expand_logical(struct expression *expr)
}
}
-static void expand_binop(struct expression *expr)
-{
- expand_int_binop(expr);
-}
-
static void expand_comma(struct expression *expr)
{
- if (expr->left->type == EXPR_VALUE)
+ if (expr->left->type == EXPR_VALUE || expr->left->type == EXPR_FVALUE)
*expr = *expr->right;
}
@@ -246,7 +340,9 @@ static void expand_compare(struct expression *expr)
expr->value = compare_types(op, left->symbol, right->symbol);
return;
}
- simplify_cmp_binop(expr, expr->ctype);
+ if (simplify_cmp_binop(expr, left->ctype))
+ return;
+ simplify_float_cmp(expr, left->ctype);
}
static void expand_conditional(struct expression *expr)
@@ -298,31 +394,53 @@ static void expand_dereference(struct expression *expr)
if (value->type == EXPR_VALUE) {
expr->type = EXPR_VALUE;
expr->value = value->value;
+ } else if (value->type == EXPR_FVALUE) {
+ expr->type = EXPR_FVALUE;
+ expr->fvalue = value->fvalue;
}
}
}
}
}
-static void simplify_preop(struct expression *expr)
+static int simplify_preop(struct expression *expr)
{
struct expression *op = expr->unop;
unsigned long long v, mask;
if (op->type != EXPR_VALUE)
- return;
+ return 0;
v = op->value;
switch (expr->op) {
case '+': break;
case '-': v = -v; break;
case '!': v = !v; break;
case '~': v = ~v; break;
- default: return;
+ default: return 0;
}
mask = 1ULL << (expr->ctype->bit_size-1);
mask = mask | (mask-1);
expr->value = v & mask;
expr->type = EXPR_VALUE;
+ return 1;
+}
+
+static int simplify_float_preop(struct expression *expr)
+{
+ struct expression *op = expr->unop;
+ long double v;
+
+ if (op->type != EXPR_FVALUE)
+ return 0;
+ v = op->fvalue;
+ switch (expr->op) {
+ case '+': break;
+ case '-': v = -v; break;
+ default: return 0;
+ }
+ expr->fvalue = v;
+ expr->type = EXPR_FVALUE;
+ return 1;
}
/*
@@ -355,7 +473,9 @@ static void expand_preop(struct expression *expr)
default:
break;
}
- simplify_preop(expr);
+ if (simplify_preop(expr))
+ return;
+ simplify_float_preop(expr);
}
static void expand_arguments(struct expression_list *head)
@@ -374,7 +494,7 @@ static void expand_cast(struct expression *expr)
expand_expression(target);
/* Simplify normal integer casts.. */
- if (target->type == EXPR_VALUE)
+ if (target->type == EXPR_VALUE || target->type == EXPR_FVALUE)
cast_value(expr, expr->ctype, target, target->ctype);
}
@@ -426,7 +546,7 @@ static void expand_expression(struct expression *expr)
switch (expr->type) {
case EXPR_VALUE:
- return;
+ case EXPR_FVALUE:
case EXPR_STRING:
return;
case EXPR_TYPE:
diff --git a/expression.c b/expression.c
index af1ed3d1..46ed9a34 100644
--- a/expression.c
+++ b/expression.c
@@ -8,6 +8,7 @@
*
* This is the expression parsing part of parsing C.
*/
+#define _ISOC99_SOURCE
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
@@ -100,18 +101,6 @@ static struct token *string_expression(struct token *token, struct expression *e
return next;
}
-static void get_fp_value(struct expression *expr, struct token *token)
-{
- static int fp_warned;
-
- expr->ctype = &double_ctype;
- expr->value = 0;
- if (!fp_warned) {
- warn(token->pos, "FP values not yet implemented");
- fp_warned = 1;
- }
-}
-
#ifndef ULLONG_MAX
#define ULLONG_MAX (~0ULL)
#endif
@@ -129,7 +118,7 @@ static void get_number_value(struct expression *expr, struct token *token)
errno = 0;
value = strtoull(str, &end, 0);
if (end == str)
- goto Enoint;
+ goto Float;
if (value == ULLONG_MAX && errno == ERANGE)
overflow = 1;
while (1) {
@@ -146,7 +135,7 @@ static void get_number_value(struct expression *expr, struct token *token)
end++;
}
} else
- goto Enoint;
+ goto Float;
if (modifiers & added)
goto Enoint;
modifiers |= added;
@@ -213,8 +202,29 @@ got_it:
Eoverflow:
error(expr->pos, "constant %s is too big even for unsigned long long",
show_token(token));
+ return;
+Float:
+ expr->fvalue = strtold(str, &end);
+ if (str == end)
+ goto Enoint;
+
+ if (*end && end[1])
+ goto Enoint;
+
+ if (*end == 'f' || *end == 'F')
+ expr->ctype = &float_ctype;
+ else if (*end == 'l' || *end == 'L')
+ expr->ctype = &ldouble_ctype;
+ else if (!*end)
+ expr->ctype = &double_ctype;
+ else
+ goto Enoint;
+
+ expr->type = EXPR_FVALUE;
+ return;
+
Enoint:
- get_fp_value(expr, token);
+ error(expr->pos, "constant %s is not a valid number", show_token(token));
}
struct token *primary_expression(struct token *token, struct expression **tree)
diff --git a/expression.h b/expression.h
index 5845e0f4..5d5612de 100644
--- a/expression.h
+++ b/expression.h
@@ -38,6 +38,7 @@ enum expression_type {
EXPR_IDENTIFIER, // identifier in initializer
EXPR_INDEX, // index in initializer
EXPR_POS, // position in initializer
+ EXPR_FVALUE,
};
struct expression {
@@ -49,6 +50,9 @@ struct expression {
// EXPR_VALUE
unsigned long long value;
+ // EXPR_FVALUE
+ long double fvalue;
+
// EXPR_STRING
struct string *string;
diff --git a/inline.c b/inline.c
index 8a07c57f..5dc49fb7 100644
--- a/inline.c
+++ b/inline.c
@@ -77,6 +77,7 @@ static struct expression * copy_expression(struct expression *expr)
/* Atomics, never change, just return the expression directly */
case EXPR_VALUE:
case EXPR_STRING:
+ case EXPR_FVALUE:
break;
/* Unops: check if the subexpression is unique */
diff --git a/linearize.c b/linearize.c
index 1fdb55bd..0992c6d1 100644
--- a/linearize.c
+++ b/linearize.c
@@ -94,6 +94,10 @@ static void show_instruction(struct instruction *insn)
printf("\t%%r%d <- %lld\n",
insn->target->nr, expr->value);
break;
+ case EXPR_FVALUE:
+ printf("\t%%r%d <- %Lf\n",
+ insn->target->nr, expr->fvalue);
+ break;
case EXPR_STRING:
printf("\t%%r%d <- %s\n",
insn->target->nr, show_string(expr->string));
@@ -411,6 +415,7 @@ static pseudo_t linearize_access(struct entrypoint *ep, struct expression *expr)
return linearize_load_gen(ep, expr, addr);
}
+/* FIXME: FP */
static pseudo_t linearize_inc_dec(struct entrypoint *ep, struct expression *expr, int postop)
{
pseudo_t addr = linearize_address_gen(ep, expr->unop);
@@ -631,6 +636,10 @@ pseudo_t linearize_cond_branch(struct entrypoint *ep, struct expression *expr, s
case EXPR_VALUE:
add_goto(ep, expr->value ? bb_true : bb_false);
return VOID;
+
+ case EXPR_FVALUE:
+ add_goto(ep, expr->fvalue ? bb_true : bb_false);
+ return VOID;
case EXPR_LOGICAL:
linearize_logical_branch(ep, expr, bb_true, bb_false);
@@ -693,7 +702,7 @@ pseudo_t linearize_expression(struct entrypoint *ep, struct expression *expr)
return VOID;
switch (expr->type) {
- case EXPR_VALUE: case EXPR_STRING: case EXPR_SYMBOL:
+ case EXPR_VALUE: case EXPR_STRING: case EXPR_SYMBOL: case EXPR_FVALUE:
return add_setval(ep, expr->ctype, expr);
case EXPR_STATEMENT:
diff --git a/show-parse.c b/show-parse.c
index 517719b7..efe55811 100644
--- a/show-parse.c
+++ b/show-parse.c
@@ -842,6 +842,15 @@ static int show_value(struct expression *expr)
return new;
}
+static int show_fvalue(struct expression *expr)
+{
+ int new = new_pseudo();
+ long double value = expr->fvalue;
+
+ printf("\tmovf.%d\t\tv%d,$%Lf\n", expr->ctype->bit_size, new, value);
+ return new;
+}
+
static int show_string_expr(struct expression *expr)
{
int new = new_pseudo();
@@ -969,6 +978,8 @@ int show_expression(struct expression *expr)
return show_cast_expr(expr);
case EXPR_VALUE:
return show_value(expr);
+ case EXPR_FVALUE:
+ return show_fvalue(expr);
case EXPR_STRING:
return show_string_expr(expr);
case EXPR_BITFIELD:
diff --git a/symbol.c b/symbol.c
index 8d887919..c4412500 100644
--- a/symbol.c
+++ b/symbol.c
@@ -345,7 +345,7 @@ static void expand_constant_p(struct expression *expr)
int value = 1;
FOR_EACH_PTR (arglist, arg) {
- if (arg->type != EXPR_VALUE)
+ if (arg->type != EXPR_VALUE && arg->type != EXPR_VALUE)
value = 0;
} END_FOR_EACH_PTR;