Linux-Sparse Archive on lore.kernel.org
 help / color / Atom feed
* [PATCH 0/4] fix usual conversion of integers
@ 2020-10-05 23:03 Luc Van Oostenryck
  2020-10-05 23:03 ` [PATCH 1/4] add builtin type pointer to bool: bool_ptr_ctype Luc Van Oostenryck
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Luc Van Oostenryck @ 2020-10-05 23:03 UTC (permalink / raw)
  To: linux-sparse; +Cc: Luc Van Oostenryck

The current implementation of the usual conversion doesn't handle
correctly the case of 'long' + 'unsigned int' on a 32-bit arch.
The resulting type is 'unsigned int' instead of 'unsigned long'.

Fix this by following closely the C99's wording.
This now gives the expected result for C89 & C99 on 32 & 64-bit archs
(as tested with the GCC testsuite).

Luc Van Oostenryck (4):
  add builtin type pointer to bool: bool_ptr_ctype
  fix prototype of __sync_bool_compare_and_swap()
  fix evaluation of pointer to bool conversions
  fix usual conversion of integers

 builtin.c                          |  2 +-
 evaluate.c                         | 67 ++++++++++++++++--------------
 symbol.c                           |  2 +
 symbol.h                           |  1 +
 validation/linear/bool-cast-lp32.c |  1 -
 5 files changed, 40 insertions(+), 33 deletions(-)

-- 
2.28.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 1/4] add builtin type pointer to bool: bool_ptr_ctype
  2020-10-05 23:03 [PATCH 0/4] fix usual conversion of integers Luc Van Oostenryck
@ 2020-10-05 23:03 ` Luc Van Oostenryck
  2020-10-05 23:03 ` [PATCH 2/4] fix prototype of __sync_bool_compare_and_swap() Luc Van Oostenryck
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Luc Van Oostenryck @ 2020-10-05 23:03 UTC (permalink / raw)
  To: linux-sparse; +Cc: Luc Van Oostenryck

This builtin type is needed for __sync_bool_compare_and_swap()'s
prototype.

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 symbol.c | 2 ++
 symbol.h | 1 +
 2 files changed, 3 insertions(+)

diff --git a/symbol.c b/symbol.c
index 7f0c85580f06..d91fd296dd32 100644
--- a/symbol.c
+++ b/symbol.c
@@ -782,6 +782,7 @@ struct symbol	bool_ctype, void_ctype, type_ctype,
 		incomplete_ctype, label_ctype, bad_ctype,
 		null_ctype;
 struct symbol	autotype_ctype;
+struct symbol	bool_ptr_ctype;
 struct symbol	int_ptr_ctype, uint_ptr_ctype;
 struct symbol	long_ptr_ctype, ulong_ptr_ctype;
 struct symbol	llong_ptr_ctype, ullong_ptr_ctype;
@@ -876,6 +877,7 @@ static const struct ctype_declare {
 	{ &null_ctype,         T_PTR(&void_ctype) },
 	{ &label_ctype,        T_PTR(&void_ctype) },
 	{ &lazy_ptr_ctype,     T_PTR(&void_ctype) },
+	{ &bool_ptr_ctype,     T_PTR(&bool_ctype) },
 	{ &int_ptr_ctype,      T_PTR(&int_ctype) },
 	{ &uint_ptr_ctype,     T_PTR(&uint_ctype) },
 	{ &long_ptr_ctype,     T_PTR(&long_ctype) },
diff --git a/symbol.h b/symbol.h
index a3ed95678ee5..47550e032589 100644
--- a/symbol.h
+++ b/symbol.h
@@ -298,6 +298,7 @@ extern struct symbol	bool_ctype, void_ctype, type_ctype,
 			incomplete_ctype, label_ctype, bad_ctype,
 			null_ctype;
 extern struct symbol	autotype_ctype;
+extern struct symbol	bool_ptr_ctype;
 extern struct symbol	int_ptr_ctype, uint_ptr_ctype;
 extern struct symbol	long_ptr_ctype, ulong_ptr_ctype;
 extern struct symbol	llong_ptr_ctype, ullong_ptr_ctype;
-- 
2.28.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 2/4] fix prototype of __sync_bool_compare_and_swap()
  2020-10-05 23:03 [PATCH 0/4] fix usual conversion of integers Luc Van Oostenryck
  2020-10-05 23:03 ` [PATCH 1/4] add builtin type pointer to bool: bool_ptr_ctype Luc Van Oostenryck
@ 2020-10-05 23:03 ` Luc Van Oostenryck
  2020-10-05 23:04 ` [PATCH 3/4] fix evaluation of pointer to bool conversions Luc Van Oostenryck
  2020-10-05 23:04 ` [PATCH 4/4] fix usual conversion of integers Luc Van Oostenryck
  3 siblings, 0 replies; 5+ messages in thread
From: Luc Van Oostenryck @ 2020-10-05 23:03 UTC (permalink / raw)
  To: linux-sparse; +Cc: Luc Van Oostenryck

The prototype was incomplete and typechecking failed after
some changes in the usual conversions.

So, add the full prototype.

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 builtin.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/builtin.c b/builtin.c
index 26b612dc401b..b134754b5831 100644
--- a/builtin.c
+++ b/builtin.c
@@ -607,7 +607,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", &bool_ctype, 1, { &ptr_ctype }, .op = &sync_compare_and_swap_op},
+	{ "__sync_bool_compare_and_swap", &bool_ctype, 1, { &bool_ptr_ctype, &bool_ctype, &bool_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 }},
-- 
2.28.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 3/4] fix evaluation of pointer to bool conversions
  2020-10-05 23:03 [PATCH 0/4] fix usual conversion of integers Luc Van Oostenryck
  2020-10-05 23:03 ` [PATCH 1/4] add builtin type pointer to bool: bool_ptr_ctype Luc Van Oostenryck
  2020-10-05 23:03 ` [PATCH 2/4] fix prototype of __sync_bool_compare_and_swap() Luc Van Oostenryck
@ 2020-10-05 23:04 ` Luc Van Oostenryck
  2020-10-05 23:04 ` [PATCH 4/4] fix usual conversion of integers Luc Van Oostenryck
  3 siblings, 0 replies; 5+ messages in thread
From: Luc Van Oostenryck @ 2020-10-05 23:04 UTC (permalink / raw)
  To: linux-sparse; +Cc: Luc Van Oostenryck

The pointer to bool conversion used an indirect intermediate
conversion to an int because the pointer was compared to 0
and not to a null pointer. The final result is the same
but the intermediate conversion generated an unneeded OP_PTRTOU
instruction which made fail some tests.

Fix this by directly comparing to a null pointer of the same
type as the type to convert.

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 evaluate.c                         | 2 ++
 validation/linear/bool-cast-lp32.c | 1 -
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/evaluate.c b/evaluate.c
index c1ef348a475e..2f3dc06f8ccb 100644
--- a/evaluate.c
+++ b/evaluate.c
@@ -2883,6 +2883,8 @@ static struct symbol *cast_to_bool(struct expression *expr)
 		return NULL;
 
 	zero = alloc_const_expression(expr->pos, 0);
+	if (oclass & TYPE_PTR)
+		zero->ctype = otype;
 	expr->op = SPECIAL_NOTEQUAL;
 	ctype = usual_conversions(expr->op, old, zero,
 			oclass, TYPE_NUM, otype, zero->ctype);
diff --git a/validation/linear/bool-cast-lp32.c b/validation/linear/bool-cast-lp32.c
index 44a650f41e7f..7aab31dd34bf 100644
--- a/validation/linear/bool-cast-lp32.c
+++ b/validation/linear/bool-cast-lp32.c
@@ -12,7 +12,6 @@ static _Bool ffun_e(void)  { return (_Bool)ffun; }
 /*
  * check-name: bool-cast-pointer
  * check-command: test-linearize -m32 -fdump-ir $file
- * check-known-to-fail
  *
  * check-output-ignore
  * check-output-excludes: ptrtu\\.
-- 
2.28.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 4/4] fix usual conversion of integers
  2020-10-05 23:03 [PATCH 0/4] fix usual conversion of integers Luc Van Oostenryck
                   ` (2 preceding siblings ...)
  2020-10-05 23:04 ` [PATCH 3/4] fix evaluation of pointer to bool conversions Luc Van Oostenryck
@ 2020-10-05 23:04 ` Luc Van Oostenryck
  3 siblings, 0 replies; 5+ messages in thread
From: Luc Van Oostenryck @ 2020-10-05 23:04 UTC (permalink / raw)
  To: linux-sparse; +Cc: Luc Van Oostenryck

The current implementation of the usual conversion doesn't handle
correctly the case of 'long' + 'unsigned int' on a 32-bit arch.
The resulting type is 'unsigned int' instead of 'unsigned long'.

Fix this by following closely the C99's wording.
This now gives the expected result for C89 & C99 on 32 & 64-bit archs
(as tested with the GCC testsuite).

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 evaluate.c | 65 ++++++++++++++++++++++++++++--------------------------
 1 file changed, 34 insertions(+), 31 deletions(-)

diff --git a/evaluate.c b/evaluate.c
index 2f3dc06f8ccb..9106aa340649 100644
--- a/evaluate.c
+++ b/evaluate.c
@@ -164,49 +164,52 @@ static inline struct symbol *integer_promotion(struct symbol *type)
 }
 
 /*
- * integer part of usual arithmetic conversions:
- *	integer promotions are applied
- *	if left and right are identical, we are done
- *	if signedness is the same, convert one with lower rank
- *	unless unsigned argument has rank lower than signed one, convert the
- *	signed one.
- *	if signed argument is bigger than unsigned one, convert the unsigned.
- *	otherwise, convert signed.
- *
- * Leaving aside the integer promotions, that is equivalent to
- *	if identical, don't convert
- *	if left is bigger than right, convert right
- *	if right is bigger than left, convert right
- *	otherwise, if signedness is the same, convert one with lower rank
- *	otherwise convert the signed one.
+ * After integer promotons:
+ * If both types are the same
+ *   -> no conversion needed
+ * If the types have the same signedness (their rank must be different)
+ *   -> convert to the type of the highest rank
+ * If rank(unsigned type) >= rank(signed type)
+ *   -> convert to the unsigned type
+ * If size(signed type) > size(unsigned type)
+ *   -> convert to the signed type
+ * Otherwise
+ *   -> convert to the unsigned type corresponding to the signed type.
  */
 static struct symbol *bigger_int_type(struct symbol *left, struct symbol *right)
 {
+	static struct symbol *unsigned_types[] = {
+		[0] = &uint_ctype,
+		[1] = &ulong_ctype,
+		[2] = &ullong_ctype,
+		[3] = &uint128_ctype,
+	};
 	unsigned long lmod, rmod;
+	struct symbol *stype, *utype;
 
 	left = integer_promotion(left);
 	right = integer_promotion(right);
 
 	if (left == right)
-		goto left;
-
-	if (left->bit_size > right->bit_size)
-		goto left;
-
-	if (right->bit_size > left->bit_size)
-		goto right;
+		return left;
 
 	lmod = left->ctype.modifiers;
 	rmod = right->ctype.modifiers;
-	if ((lmod ^ rmod) & MOD_UNSIGNED) {
-		if (lmod & MOD_UNSIGNED)
-			goto left;
-	} else if (left->rank > right->rank)
-		goto left;
-right:
-	left = right;
-left:
-	return left;
+	if (((lmod ^ rmod) & MOD_UNSIGNED) == 0)
+		return (left->rank > right->rank) ? left : right;
+	if (lmod & MOD_UNSIGNED) {
+		utype = left;
+		stype = right;
+	} else {
+		stype = left;
+		utype = right;
+	}
+	if (utype->rank >= stype->rank)
+		return utype;
+	if (stype->bit_size > utype->bit_size)
+		return stype;
+	utype = unsigned_types[stype->rank];
+	return utype;
 }
 
 static int same_cast_type(struct symbol *orig, struct symbol *new)
-- 
2.28.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, back to index

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-10-05 23:03 [PATCH 0/4] fix usual conversion of integers Luc Van Oostenryck
2020-10-05 23:03 ` [PATCH 1/4] add builtin type pointer to bool: bool_ptr_ctype Luc Van Oostenryck
2020-10-05 23:03 ` [PATCH 2/4] fix prototype of __sync_bool_compare_and_swap() Luc Van Oostenryck
2020-10-05 23:04 ` [PATCH 3/4] fix evaluation of pointer to bool conversions Luc Van Oostenryck
2020-10-05 23:04 ` [PATCH 4/4] fix usual conversion of integers Luc Van Oostenryck

Linux-Sparse Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-sparse/0 linux-sparse/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-sparse linux-sparse/ https://lore.kernel.org/linux-sparse \
		linux-sparse@vger.kernel.org
	public-inbox-index linux-sparse

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-sparse


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git