C-sparse
view release on metacpan or search on metacpan
src/sparse-0.4.4/expand.c view on Meta::CPAN
#include <limits.h>
#include "lib.h"
#include "allocate.h"
#include "parse.h"
#include "token.h"
#include "symbol.h"
#include "target.h"
#include "expression.h"
/* Random cost numbers */
#define SIDE_EFFECTS 10000 /* The expression has side effects */
#define UNSAFE 100 /* The expression may be "infinitely costly" due to exceptions */
#define SELECT_COST 20 /* Cut-off for turning a conditional into a select */
#define BRANCH_COST 10 /* Cost of a conditional branch */
static int expand_expression(SCTX_ struct expression *);
static int expand_statement(SCTX_ struct statement *);
#ifndef DO_CTX
static int conservative;
#endif
static int expand_symbol_expression(SCTX_ struct expression *expr)
{
struct symbol *sym = expr->symbol;
if (sym == &sctxp zero_int) {
if (sctxp Wundef)
warning(sctx_ expr->pos->pos, "undefined preprocessor identifier '%s'", show_ident(sctx_ expr->symbol_name));
expr->type = EXPR_VALUE;
expr->value = 0;
expr->taint = 0;
return 0;
}
/* The cost of a symbol expression is lower for on-stack symbols */
return (sym->ctype.modifiers & (MOD_STATIC | MOD_EXTERN)) ? 2 : 1;
}
static long long get_longlong(SCTX_ 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(SCTX_ 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, signmask;
long long oldmask, oldsignmask, dropped;
if (newtype->ctype.base_type == &sctxp fp_type ||
oldtype->ctype.base_type == &sctxp fp_type)
goto Float;
// For pointers and integers, we can just move the value around
expr->type = EXPR_VALUE;
expr->taint = old->taint;
if (old_size == new_size) {
expr->value = old->value;
return;
}
// expand it to the full "long long" value
value = get_longlong(sctx_ old);
Int:
// _Bool requires a zero test rather than truncation.
if (is_bool_type(sctx_ newtype)) {
expr->value = !!value;
if (!sctxp conservative && value != 0 && value != 1)
warning(sctx_ old->pos->pos, "odd constant _Bool cast (%llx becomes 1)", value);
return;
}
// Truncate it to the new size
signmask = 1ULL << (new_size-1);
mask = signmask | (signmask-1);
expr->value = value & mask;
// Stop here unless checking for truncation
if (!sctxp Wcast_truncate || sctxp conservative)
return;
// Check if we dropped any bits..
oldsignmask = 1ULL << (old_size-1);
oldmask = oldsignmask | (oldsignmask-1);
dropped = oldmask & ~mask;
// OK if the bits were (and still are) purely sign bits
if (value & dropped) {
if (!(value & oldsignmask) || !(value & signmask) || (value & dropped) != dropped)
warning(sctx_ old->pos->pos, "cast truncates bits from constant value (%llx becomes %llx)",
value & oldmask,
value & mask);
}
return;
Float:
if (!is_float_type(sctx_ newtype)) {
value = (long long)old->fvalue;
expr->type = EXPR_VALUE;
expr->taint = 0;
goto Int;
}
if (!is_float_type(sctx_ oldtype))
expr->fvalue = (long double)get_longlong(sctx_ old);
else
expr->fvalue = old->fvalue;
if (!(newtype->ctype.modifiers & MOD_LONGLONG) && \
!(newtype->ctype.modifiers & MOD_LONGLONGLONG)) {
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(SCTX_ struct expression *expr, struct symbol *ctype, unsigned int count)
{
warning(sctx_ expr->pos->pos, "shift too big (%u) for type %s", count, show_typename(sctx_ ctype));
count &= ctype->bit_size-1;
return count;
}
/*
* CAREFUL! We need to get the size and sign of the
* result right!
*/
#define CONVERT(op,s) (((op)<<1)+(s))
#define SIGNED(op) CONVERT(op, 1)
#define UNSIGNED(op) CONVERT(op, 0)
static int simplify_int_binop(SCTX_ struct expression *expr, struct symbol *ctype)
{
struct expression *left = expr->left, *right = expr->right;
unsigned long long v, l, r, mask;
signed long long sl, sr;
int is_signed;
if (right->type != EXPR_VALUE)
return 0;
r = right->value;
if (expr->op == SPECIAL_LEFTSHIFT || expr->op == SPECIAL_RIGHTSHIFT) {
if (r >= ctype->bit_size) {
if (sctxp conservative)
return 0;
r = check_shift_count(sctx_ expr, ctype, r);
right->value = r;
}
( run in 2.656 seconds using v1.01-cache-2.11-cpan-71847e10f99 )