diff mbox

[2/2] add support for __int128

Message ID 20161209230311.36024-3-luc.vanoostenryck@gmail.com (mailing list archive)
State Mainlined, archived
Headers show

Commit Message

Luc Van Oostenryck Dec. 9, 2016, 11:03 p.m. UTC
There is already support for __int128_t & __uint128_t but not yet
for GCC's __int128.

This patch add support for it and a couple of test cases.

Note: it's slightly more tricky that it look because contrary to
'__int128_t', '__int128' is not an exact type (it can still receive
the 'unsigned' or 'signed' specifier).

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 parse.c             | 10 +++++++++
 validation/int128.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 68 insertions(+)
 create mode 100644 validation/int128.c

Comments

Christopher Li Feb. 7, 2017, 2:34 a.m. UTC | #1
On Sat, Dec 10, 2016 at 7:03 AM, Luc Van Oostenryck
<luc.vanoostenryck@gmail.com> wrote:
> There is already support for __int128_t & __uint128_t but not yet
> for GCC's __int128.
>
> This patch add support for it and a couple of test cases.
>
> Note: it's slightly more tricky that it look because contrary to
> '__int128_t', '__int128' is not an exact type (it can still receive
> the 'unsigned' or 'signed' specifier).
>
> @@ -1496,6 +1504,8 @@ static struct token *declaration_specifiers(struct token *token, struct decl_sta
>                         }
>                         seen |= s->op->set;
>                         class += s->op->class;
> +                       if (s->op->set & Set_Int128)
> +                               size = 2;
>                         if (s->op->type & KW_SHORT) {
>                                 size = -1;
>                         } else if (s->op->type & KW_LONG && size++) {

This patch is already applied in sparse-next.
But I have a question regarding the "size = 2;" Is the number 2 a magic
number?

Chris
--
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
Christopher Li Feb. 7, 2017, 3:05 a.m. UTC | #2
On Tue, Feb 7, 2017 at 10:49 AM, Luc Van Oostenryck
<luc.vanoostenryck@gmail.com> wrote:
>>> @@ -1496,6 +1504,8 @@ static struct token *declaration_specifiers(struct token *token, struct decl_sta
>>>                         }
>>>                         seen |= s->op->set;
>>>                         class += s->op->class;
>>> +                       if (s->op->set & Set_Int128)
>>> +                               size = 2;
>>>                         if (s->op->type & KW_SHORT) {
>>>                                 size = -1;
>>>                         } else if (s->op->type & KW_LONG && size++) {
>>
>> This patch is already applied in sparse-next.
>> But I have a question regarding the "size = 2;" Is the number 2 a magic
>> number?
>
> Not really magic but certainly not obvious:
> * 'size' acts here as a sort of modifiers for interger
> * plain integer, 'int' thus, are set to 'size = 0'
> * then if 'short' is encountered, it's set to 'size = -1'
> * each 'long' increment size by 1
> * so int = 0, long = 1, long long = 2 & long long long = 3
> * here __int128 is in fact 'long long long' so should ends to 3
>   but the code contained a 'size++' which explain the 'size = 2'
>   I had to had to support this type.
>
> To be honest I don't like much what is done with this 'size' but
> it works and I always try to make the smallest change in the
> pre-existing code.
>

Adding the sparse mailing list.

Thanks for the explain regarding the size. So the size is actually the
how many extra int in terms of size.

In that case, maybe we can add define/enum SIZE_128_BIT as 2,
SIZE_SHORT as -1 etc together with your comment.

Chris
--
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
Luc Van Oostenryck Feb. 7, 2017, 2:40 p.m. UTC | #3
On Tue, Feb 07, 2017 at 11:05:19AM +0800, Christopher Li wrote:
> On Tue, Feb 7, 2017 at 10:49 AM, Luc Van Oostenryck
> <luc.vanoostenryck@gmail.com> wrote:
> >>> @@ -1496,6 +1504,8 @@ static struct token *declaration_specifiers(struct token *token, struct decl_sta
> >>>                         }
> >>>                         seen |= s->op->set;
> >>>                         class += s->op->class;
> >>> +                       if (s->op->set & Set_Int128)
> >>> +                               size = 2;
> >>>                         if (s->op->type & KW_SHORT) {
> >>>                                 size = -1;
> >>>                         } else if (s->op->type & KW_LONG && size++) {
> >>
> >> This patch is already applied in sparse-next.
> >> But I have a question regarding the "size = 2;" Is the number 2 a magic
> >> number?
> >
> > Not really magic but certainly not obvious:
> > * 'size' acts here as a sort of modifiers for interger
> > * plain integer, 'int' thus, are set to 'size = 0'
> > * then if 'short' is encountered, it's set to 'size = -1'
> > * each 'long' increment size by 1
> > * so int = 0, long = 1, long long = 2 & long long long = 3
> > * here __int128 is in fact 'long long long' so should ends to 3
> >   but the code contained a 'size++' which explain the 'size = 2'
> >   I had to had to support this type.
> >
> > To be honest I don't like much what is done with this 'size' but
> > it works and I always try to make the smallest change in the
> > pre-existing code.
> >
> 
> Adding the sparse mailing list.
> 
> Thanks for the explain regarding the size. So the size is actually the
> how many extra int in terms of size.
> 
> In that case, maybe we can add define/enum SIZE_128_BIT as 2,
> SIZE_SHORT as -1 etc together with your comment.

I think it would be misleading because:
* here 'size' is not directly related to the size of the integer
  (in the sizeof() sense) but is very close to the notion of 'rank'
  as used in the C standard
* __int128 is essentially 'long long long int' and as such we should
  set SIZE_128_BIT as 3 and not as 2 but here we have to *initialize*
  it to the preceding rank, 2, as the next run of the loop will
  increment it to the right value, 3.
I tried to do it in a more clear/direct way but as I had then to
duplicate some code I choose to do it with the existing code & logic.

If you wish, I'll look if I can make things a bit clearer or maybe
just adding an appropriate comment.

Luc
--
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/parse.c b/parse.c
index 808a078a..fa46758a 100644
--- a/parse.c
+++ b/parse.c
@@ -101,6 +101,7 @@  enum {
 	Set_Short = 256,
 	Set_Long = 512,
 	Set_Vlong = 1024,
+	Set_Int128 = 2048,
 	Set_Any = Set_T | Set_Short | Set_Long | Set_Signed | Set_Unsigned
 };
 
@@ -253,6 +254,12 @@  static struct symbol_op long_op = {
 	.set = Set_Long,
 };
 
+static struct symbol_op int128_op = {
+	.type = KW_SPECIFIER | KW_LONG,
+	.test = Set_S|Set_T|Set_Char|Set_Short|Set_Int|Set_Float|Set_Double|Set_Long|Set_Vlong|Set_Int128,
+	.set =  Set_T|Set_Int128,
+};
+
 static struct symbol_op if_op = {
 	.statement = parse_if_statement,
 };
@@ -408,6 +415,7 @@  static struct init_keyword {
 	{ "__signed",	NS_TYPEDEF, .op = &signed_op },
 	{ "__signed__",	NS_TYPEDEF, .op = &signed_op },
 	{ "unsigned",	NS_TYPEDEF, .op = &unsigned_op },
+	{ "__int128",	NS_TYPEDEF, .op = &int128_op },
 	{ "_Bool",	NS_TYPEDEF, .type = &bool_ctype, .op = &spec_op },
 
 	/* Predeclared types */
@@ -1496,6 +1504,8 @@  static struct token *declaration_specifiers(struct token *token, struct decl_sta
 			}
 			seen |= s->op->set;
 			class += s->op->class;
+			if (s->op->set & Set_Int128)
+				size = 2;
 			if (s->op->type & KW_SHORT) {
 				size = -1;
 			} else if (s->op->type & KW_LONG && size++) {
diff --git a/validation/int128.c b/validation/int128.c
new file mode 100644
index 00000000..53d678e2
--- /dev/null
+++ b/validation/int128.c
@@ -0,0 +1,58 @@ 
+typedef		 __int128	 int128_t;
+typedef   signed __int128	sint128_t;
+typedef unsigned __int128	uint128_t;
+
+typedef	__int128 int	badxi;
+typedef int __int128	badix;
+typedef unsigned unsigned __int128 baduu;
+typedef double __int128 baddx;
+typedef __int128 double badxd;
+
+int sizeof_int128(void)
+{
+	return sizeof(__int128);
+}
+
+typedef unsigned long long u64;
+typedef unsigned long      u32;
+
+u64 foo(u64 a, u64 b, u64 c, u32 s)
+{
+       unsigned __int128 tmp;
+
+       tmp = (((uint128_t)a) * b) + c;
+       return (u64) (tmp >> s);
+}
+
+/*
+ * check-name: int128
+ * check-command: test-linearize $file
+ * check-output-ignore
+ *
+ * check-output-contains: ret\\..*\\$16
+ * check-output-contains: mulu\\.128
+ * check-output-contains: add\\.128
+ *
+ * check-error-start
+int128.c:5:18: error: two or more data types in declaration specifiers
+int128.c:5:18: error: Trying to use reserved word 'int' as identifier
+int128.c:5:25: error: Expected ; at end of declaration
+int128.c:5:25: error: got badxi
+int128.c:6:13: error: two or more data types in declaration specifiers
+int128.c:6:13: error: Trying to use reserved word '__int128' as identifier
+int128.c:6:25: error: Expected ; at end of declaration
+int128.c:6:25: error: got badix
+int128.c:7:18: error: impossible combination of type specifiers: unsigned unsigned
+int128.c:7:18: error: Trying to use reserved word 'unsigned' as identifier
+int128.c:7:27: error: Expected ; at end of declaration
+int128.c:7:27: error: got __int128
+int128.c:8:16: error: two or more data types in declaration specifiers
+int128.c:8:16: error: Trying to use reserved word '__int128' as identifier
+int128.c:8:25: error: Expected ; at end of declaration
+int128.c:8:25: error: got baddx
+int128.c:9:18: error: two or more data types in declaration specifiers
+int128.c:9:18: error: Trying to use reserved word 'double' as identifier
+int128.c:9:25: error: Expected ; at end of declaration
+int128.c:9:25: error: got badxd
+ * check-error-end
+ */