aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2020-08-07 21:55:38 +0200
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2020-08-07 22:39:31 +0200
commit561d0af146666fde424da06a994b9f9016ba6e05 (patch)
tree07b5f3e9296469c361a3944a75be133fbc4b2e06
parentb0bd7d895a023b2ff71231ae7c1c5aee690f8a2a (diff)
downloadsparse-561d0af146666fde424da06a994b9f9016ba6e05.tar.gz
add builtin support for __sync_{bool,val}_compare_and_swap()
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@intel.com> Link: https://lore.kernel.org/lkml/202008072005.Myrby1lg%25lkp@intel.com/ Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
-rw-r--r--builtin.c60
-rw-r--r--validation/builtin-sync-cas.c1
2 files changed, 58 insertions, 3 deletions
diff --git a/builtin.c b/builtin.c
index f29b4a8d..2e9be8be 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 e289eba2..846e21bb 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)