@@ -130,6 +130,7 @@ struct symbol_op {
extern int expand_safe_p(struct expression *expr, int cost);
extern int expand_constant_p(struct expression *expr, int cost);
+extern int expand_bswap(struct expression *expr, int cost);
#define SYM_ATTR_WEAK 0
#define SYM_ATTR_NORMAL 1
@@ -819,40 +819,6 @@ void declare_builtin_functions(void)
add_pre_buffer("extern int __builtin_popcountl(unsigned long);\n");
add_pre_buffer("extern int __builtin_popcountll(unsigned long long);\n");
- /* And byte swaps.. */
- add_pre_buffer("extern unsigned short ____builtin_bswap16(unsigned short);\n");
- add_pre_buffer("extern unsigned int ____builtin_bswap32(unsigned int);\n");
- add_pre_buffer("extern unsigned long long ____builtin_bswap64(unsigned long long);\n");
- add_pre_buffer("#define __sparse_constant_swab16(x) ((unsigned short)("
- " (((unsigned short)(x) & (unsigned short)0x00ffU) << 8) |"
- " (((unsigned short)(x) & (unsigned short)0xff00U) >> 8)))\n");
- add_pre_buffer("#define __sparse_constant_swab32(x) ((unsigned int)("
- " (((unsigned int)(x) & (unsigned int)0x000000ffUL) << 24) |"
- " (((unsigned int)(x) & (unsigned int)0x0000ff00UL) << 8) |"
- " (((unsigned int)(x) & (unsigned int)0x00ff0000UL) >> 8) |"
- " (((unsigned int)(x) & (unsigned int)0xff000000UL) >> 24)))\n");
- add_pre_buffer("#define __sparse_constant_swab64(x) ((unsigned long long)("
- " (((unsigned long long)(x) & (unsigned long long)0x00000000000000ffULL) << 56) |"
- " (((unsigned long long)(x) & (unsigned long long)0x000000000000ff00ULL) << 40) |"
- " (((unsigned long long)(x) & (unsigned long long)0x0000000000ff0000ULL) << 24) |"
- " (((unsigned long long)(x) & (unsigned long long)0x00000000ff000000ULL) << 8) |"
- " (((unsigned long long)(x) & (unsigned long long)0x000000ff00000000ULL) >> 8) |"
- " (((unsigned long long)(x) & (unsigned long long)0x0000ff0000000000ULL) >> 24) |"
- " (((unsigned long long)(x) & (unsigned long long)0x00ff000000000000ULL) >> 40) |"
- " (((unsigned long long)(x) & (unsigned long long)0xff00000000000000ULL) >> 56)))\n");
- add_pre_buffer("#define __builtin_bswap16(x)"
- " (__builtin_constant_p((unsigned short)(x)) ?"
- " __sparse_constant_swab16(x) :"
- " ____builtin_bswap16(x))\n");
- add_pre_buffer("#define __builtin_bswap32(x)"
- " (__builtin_constant_p((unsigned int)(x)) ?"
- " __sparse_constant_swab32(x) :"
- " ____builtin_bswap32(x))\n");
- add_pre_buffer("#define __builtin_bswap64(x)"
- " (__builtin_constant_p((unsigned long long)(x)) ?"
- " __sparse_constant_swab64(x) :"
- " ____builtin_bswap64(x))\n");
-
/* And atomic memory access functions.. */
add_pre_buffer("extern int __sync_fetch_and_add(void *, ...);\n");
add_pre_buffer("extern int __sync_fetch_and_sub(void *, ...);\n");
@@ -35,6 +35,9 @@ IDENT_RESERVED(__sizeof_ptr__);
IDENT_RESERVED(__builtin_types_compatible_p);
IDENT_RESERVED(__builtin_offsetof);
IDENT_RESERVED(__label__);
+IDENT(__builtin_bswap16);
+IDENT(__builtin_bswap32);
+IDENT(__builtin_bswap64);
/* Attribute names */
IDENT(packed); IDENT(__packed__);
@@ -773,6 +773,11 @@ static struct symbol_op choose_op = {
.args = arguments_choose,
};
+static struct symbol_op bswap_op = {
+ .evaluate = evaluate_to_integer,
+ .expand = expand_bswap
+};
+
/*
* Builtin functions
*/
@@ -788,6 +793,9 @@ static struct sym_init {
{ "__builtin_warning", &builtin_fn_type, MOD_TOPLEVEL, &warning_op },
{ "__builtin_expect", &builtin_fn_type, MOD_TOPLEVEL, &expect_op },
{ "__builtin_choose_expr", &builtin_fn_type, MOD_TOPLEVEL, &choose_op },
+ { "__builtin_bswap16", &builtin_fn_type, MOD_TOPLEVEL, &bswap_op },
+ { "__builtin_bswap32", &builtin_fn_type, MOD_TOPLEVEL, &bswap_op },
+ { "__builtin_bswap64", &builtin_fn_type, MOD_TOPLEVEL, &bswap_op },
{ NULL, NULL, 0 }
};
@@ -200,6 +200,11 @@ static inline struct instruction *first_
return first_ptr_list((struct ptr_list *)head);
}
+static inline struct expression *first_expression(struct expression_list *head)
+{
+ return first_ptr_list((struct ptr_list *)head);
+}
+
static inline pseudo_t first_pseudo(struct pseudo_list *head)
{
return first_ptr_list((struct ptr_list *)head);
@@ -802,6 +802,46 @@ int expand_safe_p(struct expression *exp
return 0;
}
+/* The arguments are constant if the cost of all of them is zero */
+int expand_bswap(struct expression *expr, int cost)
+{
+ struct symbol *sym;
+ struct expression_list *args = expr->args;
+ long long input;
+ int count;
+
+ if (cost)
+ return cost;
+
+ sym = expr->fn->ctype;
+ count = expression_list_size(args);
+ if (count != 1) {
+ sparse_error(expr->pos, "Invalid number of arguments for function %s (expected 1 got %d)",
+ show_ident(sym->ident), count);
+ return SIDE_EFFECTS;
+ }
+
+ input = const_expression_value(first_expression(args));
+
+ if (sym->ident == &__builtin_bswap16_ident) {
+ expr->value = __builtin_bswap16(input);
+ expr->ctype = &ushort_ctype;
+ } else if (sym->ident == &__builtin_bswap32_ident) {
+ expr->value = __builtin_bswap32(input);
+ expr->ctype = &uint_ctype;
+ } else if (sym->ident == &__builtin_bswap64_ident) {
+ expr->value = __builtin_bswap64(input);
+ expr->ctype = &ullong_ctype;
+ } else {
+ die("Unexpected __builtin_bswap symbol %s\n", show_ident(sym->ident));
+ }
+
+ expr->type = EXPR_VALUE;
+ expr->taint = 0;
+ return 0;
+}
+
+
/*
* expand a call expression with a symbol. This
* should expand builtins.
On Thu, Nov 24, 2016 at 9:36 AM, Luc Van Oostenryck <luc.vanoostenryck@gmail.com> wrote: > Small typo here: "Invaild" Good catch. The corrected patch follows: Chris