devicetree-compiler.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: David Gibson <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
To: Andrei Ziureaev <andrei.ziureaev-5wv7dgnIgG8@public.gmane.org>
Cc: robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org,
	devicetree-compiler-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Subject: Re: [PATCH v2 4/6] dtc: Add support for signed operations
Date: Mon, 3 Aug 2020 20:21:32 +1000	[thread overview]
Message-ID: <20200803102132.GH7553@yekko.fritz.box> (raw)
In-Reply-To: <20200714154542.18064-5-andrei.ziureaev-5wv7dgnIgG8@public.gmane.org>

[-- Attachment #1: Type: text/plain, Size: 7807 bytes --]

On Tue, Jul 14, 2020 at 04:45:40PM +0100, Andrei Ziureaev wrote:
> Add support for signed operations, including division, modulo, right
> shift and comparisons. Signed values are "created" by the negation and
> subtraction operators and preserved by other operators as long as the
> value stays negative. Therefore "negative" and "signed" are the same
> thing in this case. Bitwise operators always return unsigned values.
> 
> This is useful for validation with dt-schema, which uses
> arbitrary-precision arithmetic and needs explicit information about the
> sign.
> 
> The TYPE_SIGNED marker can be used by yaml and dts emitters and, if a
> plugin interface is added, by plugins.
> 
> Signed-off-by: Andrei Ziureaev <andrei.ziureaev-5wv7dgnIgG8@public.gmane.org>

Nack to this approach.

I'm pretty inclined to think that having signed arithmetic in dtc is
overkill to begin with.  But even if I'm convinced that we do need it,
then having the operator itself change the type is a really bad idea.


> ---
>  dtc-parser.y                | 81 ++++++++++++++++++++++++++++++++-----
>  dtc.h                       |  2 +
>  tests/integer-expressions.c |  8 ++++
>  3 files changed, 81 insertions(+), 10 deletions(-)
> 
> diff --git a/dtc-parser.y b/dtc-parser.y
> index 3bc1aca..a7c1777 100644
> --- a/dtc-parser.y
> +++ b/dtc-parser.y
> @@ -381,6 +381,8 @@ arrayprefix:
>  		}
>  	| arrayprefix integer_prim
>  		{
> +			struct data data = $1.data;
> +
>  			if ($1.bits < 64) {
>  				uint64_t mask = (1ULL << $1.bits) - 1;
>  				/*
> @@ -396,7 +398,10 @@ arrayprefix:
>  					      " %d-bit array element", $1.bits);
>  			}
>  
> -			$$.data = data_append_integer($1.data, $2.ull, $1.bits);
> +			if ($2.is_negative)
> +				data = data_add_marker(data, TYPE_SIGNED, NULL);
> +
> +			$$.data = data_append_integer(data, $2.ull, $1.bits);
>  		}
>  	| arrayprefix dt_ref
>  		{
> @@ -492,19 +497,31 @@ integer_rela:
>  	  integer_shift
>  	| integer_rela '<' integer_shift
>  		{
> -			$$ = (struct integer){ $1.ull < $3.ull };
> +			if ($1.is_negative || $3.is_negative)
> +				$$ = (struct integer){ (int64_t)$1.ull < (int64_t)$3.ull };
> +			else
> +				$$ = (struct integer){ $1.ull < $3.ull };
>  		}
>  	| integer_rela '>' integer_shift
>  		{
> -			$$ = (struct integer){ $1.ull > $3.ull };
> +			if ($1.is_negative || $3.is_negative)
> +				$$ = (struct integer){ (int64_t)$1.ull > (int64_t)$3.ull };
> +			else
> +				$$ = (struct integer){ $1.ull > $3.ull };
>  		}
>  	| integer_rela DT_LE integer_shift
>  		{
> -			$$ = (struct integer){ $1.ull <= $3.ull };
> +			if ($1.is_negative || $3.is_negative)
> +				$$ = (struct integer){ (int64_t)$1.ull <= (int64_t)$3.ull };
> +			else
> +				$$ = (struct integer){ $1.ull <= $3.ull };
>  		}
>  	| integer_rela DT_GE integer_shift
>  		{
> -			$$ = (struct integer){ $1.ull >= $3.ull };
> +			if ($1.is_negative || $3.is_negative)
> +				$$ = (struct integer){ (int64_t)$1.ull >= (int64_t)$3.ull };
> +			else
> +				$$ = (struct integer){ $1.ull >= $3.ull };
>  		}
>  	;
>  
> @@ -515,7 +532,13 @@ integer_shift:
>  		}
>  	| integer_shift DT_RSHIFT integer_add
>  		{
> -			$$ = (struct integer){ ($3.ull < 64) ? ($1.ull >> $3.ull) : 0 };
> +			if ($3.ull < 64)
> +				if ($1.is_negative)
> +					$$ = (struct integer){ (int64_t)$1.ull >> $3.ull };
> +				else
> +					$$ = (struct integer){ $1.ull >> $3.ull };
> +			else
> +				$$ = (struct integer){ $1.is_negative ? ~0ULL : 0 };
>  		}
>  	| integer_add
>  	;
> @@ -524,10 +547,20 @@ integer_add:
>  	  integer_add '+' integer_mul
>  		{
>  			$$ = (struct integer){ $1.ull + $3.ull };
> +
> +			if ($1.is_negative == $3.is_negative)
> +				$$.is_negative = $1.is_negative;
> +			else
> +				$$.is_negative = $1.ull < -$3.ull;
>  		}
>  	| integer_add '-' integer_mul
>  		{
>  			$$ = (struct integer){ $1.ull - $3.ull };
> +
> +			if ($1.is_negative != $3.is_negative)
> +				$$.is_negative = $1.is_negative;
> +			else
> +				$$.is_negative = $1.ull < $3.ull;
>  		}
>  	| integer_mul
>  	;
> @@ -535,12 +568,29 @@ integer_add:
>  integer_mul:
>  	  integer_mul '*' integer_unary
>  		{
> -			$$ = (struct integer){ $1.ull * $3.ull };
> +			/* For our purpose, signed multiplication is the same as
> +			 * unsigned multiplication */
> +			$$ = (struct integer){
> +				$1.ull * $3.ull,
> +				$1.is_negative != $3.is_negative
> +			};
>  		}
>  	| integer_mul '/' integer_unary
>  		{
>  			if ($3.ull != 0) {
> -				$$ = (struct integer){ $1.ull / $3.ull };
> +				if ($1.is_negative || $3.is_negative) {
> +					/* Prevent UB in signed division */
> +					if (($1.ull == (1ULL << 63)) && ($3.ull == ~0ULL))
> +						$$ = (struct integer){ $1.ull };
> +					else
> +						$$ = (struct integer){
> +							(int64_t)$1.ull / (int64_t)$3.ull
> +						};
> +
> +					$$.is_negative = $1.is_negative != $3.is_negative;
> +				} else {
> +					$$ = (struct integer){ $1.ull / $3.ull };
> +				}
>  			} else {
>  				ERROR(&@$, "Division by zero");
>  				$$ = (struct integer){ 0 };
> @@ -549,7 +599,18 @@ integer_mul:
>  	| integer_mul '%' integer_unary
>  		{
>  			if ($3.ull != 0) {
> -			$$ = (struct integer){ $1.ull % $3.ull };
> +				if ($1.is_negative || $3.is_negative) {
> +					if (($1.ull == (1ULL << 63)) && ($3.ull == ~0ULL))
> +						$$ = (struct integer){ 0 };
> +					else
> +						$$ = (struct integer){
> +							(int64_t)$1.ull % (int64_t)$3.ull
> +						};
> +
> +					$$.is_negative = $1.is_negative;
> +				} else {
> +					$$ = (struct integer){ $1.ull % $3.ull };
> +				}
>  			} else {
>  				ERROR(&@$, "Division by zero");
>  				$$ = (struct integer){ 0 };
> @@ -562,7 +623,7 @@ integer_unary:
>  	  integer_prim
>  	| '-' integer_unary
>  		{
> -			$$ = (struct integer){ -$2.ull };
> +			$$ = (struct integer){ -$2.ull, !$2.is_negative };
>  		}
>  	| '~' integer_unary
>  		{
> diff --git a/dtc.h b/dtc.h
> index ccfe689..a502bef 100644
> --- a/dtc.h
> +++ b/dtc.h
> @@ -95,6 +95,7 @@ enum markertype {
>  	REF_PHANDLE,
>  	REF_PATH,
>  	LABEL,
> +	TYPE_SIGNED,
>  	TYPE_UINT8,
>  	TYPE_UINT16,
>  	TYPE_UINT32,
> @@ -119,6 +120,7 @@ struct data {
>  
>  struct integer {
>  	uint64_t ull;
> +	bool is_negative;
>  };
>  
>  #define empty_data ((struct data){ 0 /* all .members = 0 or NULL */ })
> diff --git a/tests/integer-expressions.c b/tests/integer-expressions.c
> index 6f33d81..041efb0 100644
> --- a/tests/integer-expressions.c
> +++ b/tests/integer-expressions.c
> @@ -28,15 +28,22 @@ static struct test_expr {
>  	TE(2*3),
>  	TE(4/2),
>  	TE(10/3),
> +	TE(-10/3),
>  	TE(19%4),
> +	TE(-19%4),
>  	TE(1 << 13),
>  	TE(0x1000 >> 4),
> +	TE(-0x1000 >> 4),
>  	TE(3*2+1), TE(3*(2+1)),
>  	TE(1+2*3), TE((1+2)*3),
>  	TE(1 < 2), TE(2 < 1), TE(1 < 1),
>  	TE(1 <= 2), TE(2 <= 1), TE(1 <= 1),
>  	TE(1 > 2), TE(2 > 1), TE(1 > 1),
>  	TE(1 >= 2), TE(2 >= 1), TE(1 >= 1),
> +	TE(-1 < 1), TE(1 < -1), TE(-1 < -1),
> +	TE(-1 <= 1), TE(1 <= -1), TE(-1 <= -1),
> +	TE(-1 > 1), TE(1 > -1), TE(-1 > -1),
> +	TE(-1 >= 1), TE(1 >= -1), TE(-1 >= -1),
>  	TE(1 == 1), TE(1 == 2),
>  	TE(1 != 1), TE(1 != 2),
>  	TE(0xabcdabcd & 0xffff0000),
> @@ -50,6 +57,7 @@ static struct test_expr {
>  	TE(0 ? 17 : 39), TE(1 ? 17 : 39), TE(17 ? 0xdeadbeef : 0xabcd1234),
>  	TE(11 * 257 * 1321517ULL),
>  	TE(123456790 - 4/2 + 17%4),
> +	TE(-123456790 - -4/-2 + -17%-4),
>  };
>  
>  #define ARRAY_SIZE(x)	(sizeof(x) / sizeof((x)[0]))

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

  parent reply	other threads:[~2020-08-03 10:21 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-07-14 15:45 [PATCH v2 0/6] dtc: Add support for signed operations Andrei Ziureaev
     [not found] ` <20200714154542.18064-1-andrei.ziureaev-5wv7dgnIgG8@public.gmane.org>
2020-07-14 15:45   ` [PATCH v2 1/6] dtc: Avoid UB when shifting Andrei Ziureaev
     [not found]     ` <20200714154542.18064-2-andrei.ziureaev-5wv7dgnIgG8@public.gmane.org>
2020-07-15 10:41       ` David Gibson
2020-07-14 15:45   ` [PATCH v2 2/6] dtc: Add bytestring type Andrei Ziureaev
2020-07-14 15:45   ` [PATCH v2 3/6] dtc: Turn 'uint64_t integer' into a struct Andrei Ziureaev
2020-07-14 15:45   ` [PATCH v2 4/6] dtc: Add support for signed operations Andrei Ziureaev
     [not found]     ` <20200714154542.18064-5-andrei.ziureaev-5wv7dgnIgG8@public.gmane.org>
2020-08-03 10:21       ` David Gibson [this message]
2020-07-14 15:45   ` [PATCH v2 5/6] dtc: Preserve negative integers in yaml and dts Andrei Ziureaev
2020-07-14 15:45   ` [PATCH v2 6/6] dtc: Add sign preservation and operation tests Andrei Ziureaev

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200803102132.GH7553@yekko.fritz.box \
    --to=david-xt8fgy+axnrb3ne2bgzf6laj5h9x9tb+@public.gmane.org \
    --cc=andrei.ziureaev-5wv7dgnIgG8@public.gmane.org \
    --cc=devicetree-compiler-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).