Skip Menu |

This queue is for tickets about the Math-Int128 CPAN distribution.

Report information
The Basics
Id: 82369
Status: resolved
Worked: 30 min
Priority: 0/
Queue: Math-Int128

People
Owner: Nobody in particular
Requestors: sisyphus [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: Normal
Broken in: 0.07
Fixed in: (no value)



Subject: Won't build with MinGW (gcc-4.7.0)
Hi Salva, I using a mingw64.sf.net port of (x64) gcc-4.7.0. Somewhere between 0.06_03 (which was ok) and 0.07, the build became broken for this compiler. (Sorry - I've been rather slack as regards checking the later devel releases.) Currently, with this compiler and my x64 build of perl-5.16.0, the 'perl Makefile.PL' step issues the following warning: ################################# Warning: the following files are missing in your kit: t/Math-UInt128.t ################################# And the 'dmake' step errors out with: ################################# x86_64-w64-mingw32-gcc -c -I. -s -O2 -DWIN32 -DWIN64 -DCONSERVATIVE - DPERL_TEXTMODE_SCRIPTS -DPERL_IMPLICIT_CONTEXT -DPERL_IMPLICIT_SYS -fno- strict-aliasing -mms-bitfields -s -O2 -DVERSION=\"0.07\" - DXS_VERSION=\"0.07\" "-IC:\_64\perl516_470\lib\CORE" Int128.c In file included from Int128.xs:9:0: perl_math_int64.h:34:19: error: expected declaration specifiers or '...' before '*' token perl_math_int64.h:38:19: error: expected declaration specifiers or '...' before '*' token perl_math_int64.h:42:53: error: unknown type name 'int64_t' perl_math_int64.h:44:53: error: unknown type name 'uint64_t' perl_math_int64.h:46:19: error: expected declaration specifiers or '...' before '*' token Int128.xs: In function 'SvI128': Int128.xs:258:40: error: 'math_int64_c_api_SvU64' undeclared (first use in this function) Int128.xs:258:40: note: each undeclared identifier is reported only once for each function it appears in Int128.xs:260:36: error: 'math_int64_c_api_SvI64' undeclared (first use in this function) Int128.xs: In function 'SvU128': Int128.xs:353:40: error: 'math_int64_c_api_SvU64' undeclared (first use in this function) Int128.xs:356:33: error: unknown type name 'int64_t' Int128.xs:356:47: error: 'math_int64_c_api_SvI64' undeclared (first use in this function) Int128.xs: In function 'XS_Math__Int128__mul': Int128.xs:837:17: error: 'UINT64_MAX' undeclared (first use in this function) Int128.xs: In function 'XS_Math__UInt128__mul': Int128.xs:1281:17: error: 'UINT64_MAX' undeclared (first use in this function) Int128.xs: In function 'XS_Math__Int128_int128_mul': Int128.xs:1707:17: error: 'UINT64_MAX' undeclared (first use in this function) Int128.xs: In function 'XS_Math__Int128_uint128_mul': Int128.xs:1882:17: error: 'UINT64_MAX' undeclared (first use in this function) dmake: Error code 129, while making 'Int128.o' ################################# If the cause of the problem is not apparent to you, let me know, and I'll start digging. Cheers, Rob
El Mié Ene 02 20:05:59 2013, SISYPHUS escribió: Show quoted text
> Hi Salva, > I using a mingw64.sf.net port of (x64) gcc-4.7.0. > Somewhere between 0.06_03 (which was ok) and 0.07, the build became > broken for this compiler. (Sorry - I've been rather slack as regards > checking the later devel releases.) > > Currently, with this compiler and my x64 build of perl-5.16.0, > the 'perl Makefile.PL' step issues the following warning: > > ################################# > Warning: the following files are missing in your kit: > t/Math-UInt128.t > ################################# > > And the 'dmake' step errors out with: > > ################################# > x86_64-w64-mingw32-gcc -c -I. -s -O2 -DWIN32 -DWIN64 -DCONSERVATIVE - > DPERL_TEXTMODE_SCRIPTS -DPERL_IMPLICIT_CONTEXT -DPERL_IMPLICIT_SYS -fno- > strict-aliasing -mms-bitfields -s -O2 -DVERSION=\"0.07\" - > DXS_VERSION=\"0.07\" "-IC:\_64\perl516_470\lib\CORE" Int128.c > In file included from Int128.xs:9:0: > perl_math_int64.h:34:19: error: expected declaration specifiers > or '...' before '*' token > perl_math_int64.h:38:19: error: expected declaration specifiers > or '...' before '*' token > perl_math_int64.h:42:53: error: unknown type name 'int64_t' > perl_math_int64.h:44:53: error: unknown type name 'uint64_t'
This is probably caused by the types int64_t and uint64_t not being defined on the mingw64 environment. I have copied the definitions for the MS compilers from Math::Int64. I suppose that mingw64 also defines MS_VER macro (as it tries to emulate MS compilers), otherwise the #ifdef that controls that part should be extended to detect the mingw64 environment. Could you test the development version from GitHub? https://github.com/salva/p5-Math-Int128
I forgot to say that in order to compile from the development version you need to install Module::CAPIMaker
On Sat Jan 05 07:49:12 2013, SALVA wrote: Show quoted text
> > In file included from Int128.xs:9:0: > > perl_math_int64.h:34:19: error: expected declaration specifiers > > or '...' before '*' token > > perl_math_int64.h:38:19: error: expected declaration specifiers > > or '...' before '*' token > > perl_math_int64.h:42:53: error: unknown type name 'int64_t' > > perl_math_int64.h:44:53: error: unknown type name 'uint64_t'
> > This is probably caused by the types int64_t and uint64_t not being > defined on the mingw64 environment.
Yes, including stdint.h takes care of that, and Math-Int64-0.07 then builds fine. However, t/Math-Int128.t crashes on the line: my $k = (int128(1) << 60) + 255; The same thing happens on 0.05. With 0.05: ######################## C:\sisyphusion\Math-Int128-0.07>perl -MMath::Int128="int128" - le "$x=int128(1) << 60;print $x" [CRASH - no useful error message] C:\sisyphusion\Math-Int128-0.07>perl -MMath::Int128="int128" - le "$x=int128(1);$x <<= 60;print $x" 1152921504606846976 C:\sisyphusion\Math-Int128-0.07> ######################## And the same commands with 0.07 ######################## C:\sisyphusion\Math-Int128-0.07>perl -Mblib -MMath::Int128="int128" - le "$x=int128(1) << 60;print $x" [CRASH - no useful error message] C:\sisyphusion\Math-Int128-0.07>perl -Mblib -MMath::Int128="int128" - le "$x=int128(1);$x <<= 60;print $x" [CRASH - no useful error message] C:\sisyphusion\Math-Int128-0.07> ######################## Some problem with the overloading of '<<' I guess (haven't looked) ... interesting that '<<=' overloads ok on 0.05. Show quoted text
> Could you test the development version from GitHub? > > https://github.com/salva/p5-Math-Int128
I get: ######################## C:\sisyphusion\Math-Int128>perl Makefile.PL Checking if your kit is complete... Warning: the following files are missing in your kit: c_api.h c_api_client/perl_math_int128.c c_api_client/perl_math_int128.h c_api_client/sample.xs t/Math-UInt128.t Please inform the author. Writing Makefile for Math::Int128 Writing MYMETA.yml and MYMETA.json GNU C compiler version 4.7.0 found, good! C:\sisyphusion\Math-Int128>dmake cp lib/Math/Int128.pm blib\lib\Math\Int128.pm cp lib/Math/Int128/die_on_overflow.pm blib\lib\Math\Int128 \die_on_overflow.pm make_perl_module_c_api module_name=Math::Int128 module_version=0.07 author='Salvador Fandino <sfandino@yahoo.com>' The system cannot find the file specified. dmake: Error code 129, while making 'c_api.h' C:\sisyphusion\Math-Int128> ######################## Not sure which file it's complaining about ... certainly not c_api.decl. (If I rename c_api.decl to something else I get a different error.) Cheers, Rob
On Sat Jan 05 22:48:20 2013, SISYPHUS wrote: Show quoted text
> > Yes, including stdint.h takes care of that, and Math-Int64-0.07 then > builds fine.
s/Math\-Int64/Math\-Int128/ in the above line. Show quoted text
> However, t/Math-Int128.t crashes on the line: > my $k = (int128(1) << 60) + 255;
In the mi128_left() XSub, it's the following assignment in the CODE section's first else block that's crashing: a = SvU128x(self); Cheers, Rob
Subject: Re: [rt.cpan.org #82369] Won't build with MinGW (gcc-4.7.0)
Date: Mon, 7 Jan 2013 05:56:35 -0800 (PST)
To: "bug-Math-Int128 [...] rt.cpan.org" <bug-Math-Int128 [...] rt.cpan.org>
From: Salvador Fandino <sfandino [...] yahoo.com>
Show quoted text
----- Original Message -----
> From: Sisyphus via RT <bug-Math-Int128@rt.cpan.org> > To: > Cc: > Sent: Monday, January 7, 2013 10:15 AM > Subject: [rt.cpan.org #82369] Won't build with MinGW (gcc-4.7.0) > >       Queue: Math-Int128 > Ticket <URL: https://rt.cpan.org/Ticket/Display.html?id=82369 > > > On Sat Jan 05 22:48:20 2013, SISYPHUS wrote: >
>> >> Yes, including stdint.h takes care of that, and Math-Int64-0.07 then >> builds fine.
> > s/Math\-Int64/Math\-Int128/ in the above line. >
>> However, t/Math-Int128.t crashes on the line: >> my $k = (int128(1) << 60) + 255;
> > In the mi128_left() XSub, it's the following assignment in the CODE > section's first else block that's crashing: > >         a = SvU128x(self);
Which error do you get exactly?
On Mon Jan 07 08:56:48 2013, sfandino@yahoo.com wrote: Show quoted text
> > In the mi128_left() XSub, it's the following assignment in the CODE > > section's first else block that's crashing: > > > >         a = SvU128x(self);
> > Which error do you get exactly?
I just get a pop-up that tells me that perl.exe has stopped working. When I "cancel" the pop-up the process exists - no other information is provided. If I wait for a few moments, there's a couple of XML files and some sort of binary .mdump file that get written. (They're of no use to me ... I can send 'em to you if you think they might be of use to you.) For debugging, I applied the following patch to Int128.xs (version 0.07): ######################### --- Int128.xs_orig 2013-01-08 19:18:28 +1100 +++ Int128.xs 2013-01-08 19:22:32 +1100 @@ -6,6 +6,7 @@ #include "perl.h" #include "XSUB.h" #include "ppport.h" +#include <stdint.h> #include "perl_math_int64.h" #if __GNUC__ == 4 && __GNUC_MINOR__ >= 4 && __GNUC_MINOR__ < 6 @@ -925,6 +926,7 @@ PREINIT: int128_t a; uint128_t b; + SV * temp; CODE: if (SvTRUE(rev)) { a = SvI128(aTHX_ other); @@ -932,7 +934,10 @@ } else { b = SvI128(aTHX_ other); - a = SvU128x(self); + temp = SvSU128(aTHX_ self); + printf("string: %s\n", SvPVX(temp)); + a = *((int128_t*)SvPVX(temp)); + printf("Got to D\n"); } if (may_die_on_overflow && (b > 128)) overflow(aTHX_ left_error); if (SvOK(rev)) ######################### Then rebuild Math-Int128-0.07 and run: ######################### C:\sisyphusion\Math-Int128-0.07>perl -Mblib -MMath::Int128="int128" - le "$x=int1 28(1) << 60;print $x" string: ☺ [Usual CRASH] C:\sisyphusion\Math-Int128-0.07> ######################### UIM, that leaves the Int128.xs file essentially unchanged, and demonstrates that the crash is occurring with: a = *((int128_t*)SvPVX(temp)); (Not sure how the printf of SVPVX(temp) will display on this webpage - it's actually chr(1).) Hope to find some time, tomorrow night, to give this the attention it deserves. Cheers, Rob
On Tue Jan 08 04:22:41 2013, SISYPHUS wrote: Show quoted text
> Hope to find some time, tomorrow night, to give this the attention it > deserves.
It took a bit longer to get back to it than expected ... and having now spent some more time poking at, the only conclusion I've reached is that I'm not smart enough to debug it. I did establish that the Devel::Peek::Dump of the problem sv (which I did by inserting a callback to Devel::Peek::Dump into my modified Int128.xs) outputs: ############################## SV = PVMG(0x270cb28) at 0x39df68 REFCNT = 1 FLAGS = (OBJECT,POK,READONLY,OVERLOAD,pPOK) IV = 0 NV = 0 PV = 0x455c48 "\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"\0 CUR = 16 LEN = 24 STASH = 0x261e268 "Math::Int128" ############################## At least - that's what it is when 'dmake test' is run. For some reason, when 'perl -Mblib t/Math-Int128.t' is run, the Devel::Peek::Dump() doesn't show the trailing \0 in the PV slot (but crashes just the same, anyway). And I did write an Inline::C script that had no problem doing the a = *((int128_t*)SvPVX(temp)); when temp's Devel::Peek::Dump() looks like: ############################## SV = PV(0x82ad38) at 0x26626a0 REFCNT = 1 FLAGS = (PADMY,POK,pPOK) PV = 0x312e58 "\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"\0 CUR = 16 LEN = 24 ############################## Why would one be a problem, but the other ok ? Something to do with what's being pointed at ? Anyway, Strawberry Perl (x64) is affected in the same way, too - so I'll post to the Strawberry mailing list and see if one of the clever people over there wants to investigate it. Cheers, Rob
Attached is a patch against Int128.xs from version Math-Int128-0.12 that allows the module to build and pass all tests on Windows with gcc-4.7.0. For reasons that I don't understand, it's (apparently) ok to do 'SvI128(aTHX_ other)' and 'SvU128(aTHX_ other)' in both the CODE and PREINIT sections, and it's ok to do both 'SvI128x(self)' and 'SvU128x(self)' in the PREINIT section ... but, on Windows, you cannot do either 'SvI128x(self)' or 'SvU128x(self)' in the *CODE* section. (If you do that, you get a crash with no useful error messages.) Now, you'll notice that there are still CODE sections in the patched Int128.xs that do both 'SvI128x(self)' and 'SvU128x(self)'. I expect that these are simply "crashes waiting to happen". I patched enough merely to allow all tests to pass. Perhaps there's a better fix than that provided by my patch. For one thing, I've turned mu128_sub into an awful state that badly needs to be rewritten ... but it's getting late. And I wouldn't like to guarantee that my patched versions always do the right thing, either ;-) If you can see something in SvI128x() and SvU128x() that account for this behaviour (and can be fixed) then I would think that would be a better approach. I notice that mu128_pow assigns SvU128() and SvU128x() to int128_t variables. I expect the assignment should be to uint128_t variables ? And is the third argument (rev) to mu128_pow invariably &PL_sv_no ? If so why do you SvTRUE(rev) ? Hope there's something here that helps, at least ;-) Cheers, Rob
Subject: Int128.xs.diff
--- Int128.xs_orig 2013-07-25 12:14:18 +1000 +++ Int128.xs 2013-07-25 22:51:32 +1000 @@ -908,29 +908,27 @@ SV *other SV *rev PREINIT: - int128_t up; - int128_t down; + int128_t a = SvI128x(self); + int128_t b = SvI128(aTHX_ other); CODE: if (SvOK(rev)) { if (SvTRUE(rev)) { - up = SvI128(aTHX_ other); - down = SvI128x(self); + if (!a) + croak_string(aTHX_ div_by_0_error); + RETVAL = newSVi128(aTHX_ b / a); } else { - up = SvI128x(self); - down = SvI128(aTHX_ other); + if (!b) + croak_string(aTHX_ div_by_0_error); + RETVAL = newSVi128(aTHX_ a / b); } - if (!down) - croak_string(aTHX_ div_by_0_error); - RETVAL = newSVi128(aTHX_ up/down); } else { - down = SvI128(aTHX_ other); - if (!down) + if (!b) croak_string(aTHX_ div_by_0_error); - RETVAL = self; + a /= b; + RETVAL = newSVi128(aTHX_ a); SvREFCNT_inc(RETVAL); - SvI128x(self) /= down; } OUTPUT: RETVAL @@ -941,29 +939,25 @@ SV *other SV *rev PREINIT: - int128_t up; - int128_t down; + int128_t a = SvI128x(self); + int128_t b = SvI128(aTHX_ other); CODE: if (SvOK(rev)) { if (SvTRUE(rev)) { - up = SvI128(aTHX_ other); - down = SvI128x(self); + if (!a) + croak_string(aTHX_ div_by_0_error); + RETVAL = newSVi128(aTHX_ b % a); } else { - up = SvI128x(self); - down = SvI128(aTHX_ other); + if (!b) + croak_string(aTHX_ div_by_0_error); + RETVAL = newSVi128(aTHX_ a % b); } - if (!down) - croak_string(aTHX_ div_by_0_error); - RETVAL = newSVi128(aTHX_ up % down); } else { - down = SvI128(aTHX_ other); - if (!down) + if (!b) croak_string(aTHX_ div_by_0_error); - RETVAL = self; - SvREFCNT_inc(RETVAL); - SvI128x(self) %= down; + } OUTPUT: RETVAL @@ -1087,8 +1081,12 @@ mi128_eqn(self, other, ...) SV *self SV *other +PREINIT: + int128_t a = SvI128x(self); + int128_t b = SvI128(aTHX_ other); CODE: - RETVAL = ( SvI128x(self) == SvI128(aTHX_ other) + printf("starting _eqn\n"); + RETVAL = ( a == b ? &PL_sv_yes : &PL_sv_no ); OUTPUT: @@ -1315,22 +1313,29 @@ SV *other SV *rev PREINIT: - uint128_t a, b; + uint128_t a = SvU128x(self); + uint128_t b = SvU128(aTHX_ other); CODE: - if (SvTRUE(rev)) { - a = SvU128(aTHX_ other); - b = SvU128x(self); - } - else { - a = SvU128x(self); - b = SvU128(aTHX_ other); - } - if (may_die_on_overflow && (b > a)) overflow(aTHX_ sub_error); - if (SvOK(rev)) + if(SvOK(rev)) { + if(SvTRUE(rev)) { + if (may_die_on_overflow && (a > b)) overflow(aTHX_ sub_error); + RETVAL = newSVu128(aTHX_ b - a); + } + else { + if (may_die_on_overflow && (b > a)) overflow(aTHX_ sub_error); RETVAL = newSVu128(aTHX_ a - b); + } + } else { RETVAL = SvREFCNT_inc(self); - SvU128x(self) = a - b; + if(SvTRUE(rev)) { + if (may_die_on_overflow && (a > b)) overflow(aTHX_ sub_error); + SvU128x(self) = b - a; + } + else { + if (may_die_on_overflow && (b > a)) overflow(aTHX_ sub_error); + SvU128x(self) = a - b; + } } OUTPUT: RETVAL @@ -1355,35 +1360,34 @@ OUTPUT: RETVAL + SV * mu128_div(self, other, rev) SV *self SV *other SV *rev PREINIT: - uint128_t up; - uint128_t down; + uint128_t a = SvU128x(self); + uint128_t b = SvU128(aTHX_ other); CODE: if (SvOK(rev)) { if (SvTRUE(rev)) { - up = SvU128(aTHX_ other); - down = SvU128x(self); + if (!a) + croak_string(aTHX_ div_by_0_error); + RETVAL = newSVu128(aTHX_ b / a); } else { - up = SvU128x(self); - down = SvU128(aTHX_ other); + if (!b) + croak_string(aTHX_ div_by_0_error); + RETVAL = newSVu128(aTHX_ a / b); } - if (!down) - croak_string(aTHX_ div_by_0_error); - RETVAL = newSVu128(aTHX_ up/down); } else { - down = SvU128(aTHX_ other); - if (!down) + if (!b) croak_string(aTHX_ div_by_0_error); - RETVAL = self; + a /= b; + RETVAL = newSVi128(aTHX_ a); SvREFCNT_inc(RETVAL); - SvU128x(self) /= down; } OUTPUT: RETVAL @@ -1394,29 +1398,27 @@ SV *other SV *rev PREINIT: - uint128_t up; - uint128_t down; + uint128_t a = SvU128x(self); + uint128_t b = SvU128(aTHX_ other); CODE: if (SvOK(rev)) { if (SvTRUE(rev)) { - up = SvU128(aTHX_ other); - down = SvU128x(self); + if (!a) + croak_string(aTHX_ div_by_0_error); + RETVAL = newSVu128(aTHX_ b % a); } else { - up = SvU128x(self); - down = SvU128(aTHX_ other); + if (!b) + croak_string(aTHX_ div_by_0_error); + RETVAL = newSVu128(aTHX_ a % b); } - if (!down) - croak_string(aTHX_ div_by_0_error); - RETVAL = newSVu128(aTHX_ up % down); } else { - down = SvU128(aTHX_ other); - if (!down) + if (!b) croak_string(aTHX_ div_by_0_error); - RETVAL = self; + a %= b; + RETVAL = newSVu128(aTHX_ a); SvREFCNT_inc(RETVAL); - SvU128x(self) %= down; } OUTPUT: RETVAL @@ -1478,16 +1480,9 @@ PREINIT: int sign; uint128_t r; - int128_t a, b; + int128_t a = SvU128x(self); + int128_t b = SvU128(aTHX_ other); CODE: - if (SvTRUE(rev)) { - a = SvU128(aTHX_ other); - b = SvU128x(self); - } - else { - a = SvU128x(self); - b = SvU128(aTHX_ other); - } r = powU128(aTHX_ a, b); if (SvOK(rev)) RETVAL = newSVu128(aTHX_ r); @@ -1524,8 +1519,11 @@ mu128_eqn(self, other, ...) SV *self SV *other +PREINIT: + uint128_t a = SvU128x(self); + uint128_t b = SvU128(aTHX_ other); CODE: - RETVAL = ( SvU128x(self) == SvU128(aTHX_ other) + RETVAL = ( a == b ? &PL_sv_yes : &PL_sv_no ); OUTPUT:
On Thu Jul 25 09:13:09 2013, SISYPHUS wrote: Show quoted text
> Now, you'll notice that there are still CODE sections in the patched > Int128.xs that do both 'SvI128x(self)' and 'SvU128x(self)'. I expect > that these are simply "crashes waiting to happen".
This appears to be *not* the case. I haven't yet found any problems with any of the subs I didn't alter. This only confuses me further as to the rule(s) regarding the use of 'SvI128x(self)' and 'SvU128x(self)' in CODE sections. I'll continue to try to determine the rule(s) of engagement. Further, it seems that there was no need for me to patch mi128_eqn and mu128_eqn. (I originally patched them when 'ok (($j %= $i) == 2);' caused a crash, thinking it was the '==' sub causing the problem ... but it was only the '%=' sub that needed amendment.) Cheers, Rob
It seems the problem was that the code generated by gcc required the int128 integers to be aligned at 16-byte boundaries but the memory allocator used by Strawberry Perl only guarantees 8-byte alignment, so eventually the module crashed. I have fixed that issue on 0.13. Try it and don't hesitate to reopen the ticket if you find that the problem is still unsolved for you. https://metacpan.org/release/SALVA/Math-Int128-0.13
Just for future reference. The issue was also discussed in this PerlMonks thread: http://perlmonks.org/?node_id=1052707