[PATCH 3/3] add builtin support for __sync_{bool,val}_compare_and_swap()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



In the kernel, the architecture s390 uses these builtins to
implement __atomic_cmpxchg() and friends. These builtins
are polymorphic, so they need some special evaluation.
These builtins are known to sparse but with a return type
of 'int' and the argument's types being ignored.

A problem occurs when used on a pointer type: the expected
type doesn't match 'int' and it can give warnings like:
	warning: non size-preserving integer to pointer cast

So, improve the support for these builtins by:
*) checking the number of arguments
*) extract the type from the 1st argument
*) set the returned type to this type if needed
*) finally, do the typechecking by calling evaluate_arguments()

Reported-by: kernel test robot <lkp@xxxxxxxxx>
Link: https://lore.kernel.org/lkml/202008072005.Myrby1lg%25lkp@xxxxxxxxx/
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@xxxxxxxxx>
---
 builtin.c                     | 60 +++++++++++++++++++++++++++++++++--
 validation/builtin-sync-cas.c |  1 -
 2 files changed, 58 insertions(+), 3 deletions(-)

diff --git a/builtin.c b/builtin.c
index f29b4a8d518c..2e9be8be8adb 100644
--- a/builtin.c
+++ b/builtin.c
@@ -355,6 +355,62 @@ static struct symbol_op overflow_p_op = {
 };
 
 
+static int eval_sync_compare_and_swap(struct expression *expr)
+{
+	struct symbol_list *types = NULL;
+	struct symbol *ctype = NULL;
+	struct expression *arg;
+	int n = 0;
+
+	/* the first arg is a pointer type; we'd already verified that */
+	FOR_EACH_PTR(expr->args, arg) {
+		struct symbol *t = arg->ctype;
+
+		if (!t)
+			return 0;
+
+		// 2nd & 3rd args must be a basic integer type or a pointer
+		// 1st arg must be a pointer to such a type.
+		if (++n == 1) {
+			if (t->type == SYM_NODE)
+				t = t->ctype.base_type;
+			if (!t)
+				return 0;
+			if (t->type != SYM_PTR)
+				goto err;
+			t = t->ctype.base_type;
+			if (!t)
+				return 0;
+			if (t->type == SYM_NODE)
+				t = t->ctype.base_type;
+			if (!t)
+				return 0;
+			if (t->type != SYM_PTR && t->ctype.base_type != &int_type)
+				goto err;
+			ctype = t;
+			add_ptr_list(&types, arg->ctype);
+		} else {
+			add_ptr_list(&types, ctype);
+		}
+	} END_FOR_EACH_PTR(arg);
+
+	if (!expr->ctype)	// __sync_val_compare_and_swap()
+		expr->ctype = ctype;
+	return evaluate_arguments(types, expr->args);
+
+err:
+	sparse_error(arg->pos, "invalid type for argument %d:", n);
+	info(arg->pos, "        %s", show_typename(arg->ctype));
+	expr->ctype = &bad_ctype;
+	return 0;
+}
+
+static struct symbol_op sync_compare_and_swap_op = {
+	.args = args_triadic,
+	.evaluate = eval_sync_compare_and_swap,
+};
+
+
 /*
  * Builtin functions
  */
@@ -548,7 +604,7 @@ static const struct builtin_fn builtins_common[] = {
 
 	{ "__sync_add_and_fetch", &int_ctype, 1, { &ptr_ctype }},
 	{ "__sync_and_and_fetch", &int_ctype, 1, { &ptr_ctype }},
-	{ "__sync_bool_compare_and_swap", &int_ctype, 1, { &ptr_ctype }},
+	{ "__sync_bool_compare_and_swap", &bool_ctype, 1, { &ptr_ctype }, .op = &sync_compare_and_swap_op},
 	{ "__sync_fetch_and_add", &int_ctype, 1, { &ptr_ctype }},
 	{ "__sync_fetch_and_and", &int_ctype, 1, { &ptr_ctype }},
 	{ "__sync_fetch_and_nand", &int_ctype, 1, { &ptr_ctype }},
@@ -561,7 +617,7 @@ static const struct builtin_fn builtins_common[] = {
 	{ "__sync_or_and_fetch", &int_ctype, 1, { &ptr_ctype }},
 	{ "__sync_sub_and_fetch", &int_ctype, 1, { &ptr_ctype }},
 	{ "__sync_synchronize", &void_ctype, 0 },
-	{ "__sync_val_compare_and_swap", &int_ctype, 1, { &ptr_ctype }},
+	{ "__sync_val_compare_and_swap", NULL, 1, { &ptr_ctype }, .op = &sync_compare_and_swap_op },
 	{ "__sync_xor_and_fetch", &int_ctype, 1, { &ptr_ctype }},
 
 	{ }
diff --git a/validation/builtin-sync-cas.c b/validation/builtin-sync-cas.c
index e289eba2949b..846e21bb2fbb 100644
--- a/validation/builtin-sync-cas.c
+++ b/validation/builtin-sync-cas.c
@@ -16,7 +16,6 @@ static _Bool boz(_Bool *ptr)
 
 /*
  * check-name: builtin-sync-cas
- * check-known-to-fail
  *
  * check-error-start
 builtin-sync-cas.c:9:49: warning: incorrect type in argument 2 (different base types)
-- 
2.28.0




[Index of Archives]     [Newbies FAQ]     [LKML]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Trinity Fuzzer Tool]

  Powered by Linux