diff mbox

[v2] implement constant-folding in __builtin_bswap*()

Message ID CANeU7QmQ1pg=AjK++kG-RSX3z36qHNHPfkfi_DkeFpOLga_70w@mail.gmail.com (mailing list archive)
State Superseded, archived
Headers show

Commit Message

Christopher Li Nov. 24, 2016, 12:58 a.m. UTC
Err, forget to attach. Here is the still buggy V2 patch.

Chris

On Thu, Nov 24, 2016 at 8:56 AM, Christopher Li <sparse@chrisli.org> wrote:
> On Thu, Nov 24, 2016 at 4:48 AM, Luc Van Oostenryck
> <luc.vanoostenryck@gmail.com> wrote:
>> There is a problem though, with non-constant args.
>> Now the predeclarations of the 3 __builtin_bswap16/32/64
>> are gone, no more prototype and thus no more typing information.
>>
>> For example, if you call __builtin_bswap64() with an int argument,
>> there is no way for the next steps to know the arg must first
>> be 64 bit extended. Same for the result's type.
>
> That is a very good point. Need more work on that.
>
> The currently problem if I include the function prototype, the
> function prototype symbol will over shadow the symbol contain
> swap_op. We need to make sure the function prototype symbol
> is the one loading with correct swap_op.
>
> Ideally, all the "__builtin_xxx" related stuff should be move to a
> separate builtin.c. Right now the function prototype is in lib.c
> The implementation is sprinkle around symbol.c, evaluation.c
> and expand.c.
>
> Re-attach the V2 patch as last email I forget to CC sparse
> mailing list. This V2 patch still have the missing prototype problem
> you describe here.
>
>
> Chris

Comments

Luc Van Oostenryck Nov. 24, 2016, 1:36 a.m. UTC | #1
On Thu, Nov 24, 2016 at 08:58:35AM +0800, Christopher Li wrote:
> +/* 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, "Invaild number of arguments for function %s (expected 1 got %d)",

Small typo here: "Invaild"
--
To unsubscribe from this list: send the line "unsubscribe linux-sparse" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/expand.c b/expand.c
index 0f6720c..b9a430b 100644
--- a/expand.c
+++ b/expand.c
@@ -802,6 +802,46 @@  int expand_safe_p(struct expression *expr, int cost)
 	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, "Invaild 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.
diff --git a/ident-list.h b/ident-list.h
index b65b667..a683f6c 100644
--- a/ident-list.h
+++ b/ident-list.h
@@ -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__);
diff --git a/lib.c b/lib.c
index 2660575..7e35049 100644
--- a/lib.c
+++ b/lib.c
@@ -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");
diff --git a/lib.h b/lib.h
index b778bdc..306ee45 100644
--- a/lib.h
+++ b/lib.h
@@ -200,6 +200,11 @@  static inline struct instruction *first_instruction(struct instruction_list *hea
 	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);
diff --git a/symbol.c b/symbol.c
index 92a7a62..e57f207 100644
--- a/symbol.c
+++ b/symbol.c
@@ -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 }
 };
 
diff --git a/symbol.h b/symbol.h
index 9b3f160..48bbfce 100644
--- a/symbol.h
+++ b/symbol.h
@@ -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