Zero & sign-extensions are relatively common operations which are currently open-coded at each use. Define helpers for doing these operations. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@xxxxxxxxx> --- bits.h | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib.h | 1 + symbol.h | 8 ++++++++ 3 files changed, 70 insertions(+) create mode 100644 bits.h diff --git a/bits.h b/bits.h new file mode 100644 index 000000000..c0dc952ea --- /dev/null +++ b/bits.h @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Helper functions for manipulation & testing of integer values + * like zero or sign-extensions. + * + * Copyright (C) 2017 Luc Van Oostenryck + * + */ + +#ifndef BITS_H +#define BITS_H + +static inline unsigned long long sign_bit(unsigned size) +{ + return 1ULL << (size - 1); +} + +static inline unsigned long long sign_mask(unsigned size) +{ + unsigned long long sbit = sign_bit(size); + return sbit - 1; +} + +static inline unsigned long long bits_mask(unsigned size) +{ + unsigned long long sbit = sign_bit(size); + return sbit | (sbit - 1); +} + + +static inline long long zero_extend(long long val, unsigned size) +{ + return val & bits_mask(size); +} + +static inline long long sign_extend(long long val, unsigned size) +{ + if (val & sign_bit(size)) + val |= ~sign_mask(size); + return val; +} + +/// +// sign extend @val but only if exactly representable +static inline long long sign_extend_safe(long long val, unsigned size) +{ + unsigned long long mask = bits_mask(size); + if (!(val & ~mask)) + val = sign_extend(val, size); + return val; +} + +static inline long long bits_extend(long long val, unsigned size, int is_signed) +{ + val = zero_extend(val, size); + if (is_signed) + val = sign_extend(val, size); + return val; +} + +#endif diff --git a/lib.h b/lib.h index 7362111cd..3cd8560a5 100644 --- a/lib.h +++ b/lib.h @@ -34,6 +34,7 @@ #include "compat.h" #include "ptrlist.h" #include "utils.h" +#include "bits.h" #define DO_STRINGIFY(x) #x #define STRINGIFY(x) DO_STRINGIFY(x) diff --git a/symbol.h b/symbol.h index 6b891edd6..1cad6d052 100644 --- a/symbol.h +++ b/symbol.h @@ -453,6 +453,14 @@ static inline int get_sym_type(struct symbol *type) return type->type; } +static inline long long extend_value(long long val, struct symbol *ctype) +{ + int is_signed = !(ctype->ctype.modifiers & MOD_UNSIGNED); + unsigned size = ctype->bit_size; + + return bits_extend(val, size, is_signed); +} + static inline struct symbol *lookup_keyword(struct ident *ident, enum namespace ns) { if (!ident->keyword) -- 2.18.0 -- To unsubscribe from this list: send the line "unsubscribe linux-sparse" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html