Skip to content

t/op/pack.t fails when compiled with Open64 #12900

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
p5pRT opened this issue Apr 6, 2013 · 12 comments
Closed

t/op/pack.t fails when compiled with Open64 #12900

p5pRT opened this issue Apr 6, 2013 · 12 comments
Labels

Comments

@p5pRT
Copy link

p5pRT commented Apr 6, 2013

Migrated from rt.perl.org#117501 (status was 'resolved')

Searchable as RT117501$

@p5pRT
Copy link
Author

p5pRT commented Apr 6, 2013

From @Hugmeir

Created by @Hugmeir

$ opencc --version
Open64 Compiler Suite​: Version 4.5.2.1
Built on​: 2013-04-06 06​:04​:55 -0300
Thread model​: posix
GNU gcc version 4.2.0 (Open64 4.5.2.1 driver)

My configure line is just this​:

./Configure -des -Dusedevel -DDEBUGGING -Dcc=opencc
-Accflags='-OPT​:Olimit=0'

Besides a handful of extraneous warnings during compilation, everything
seems to work & all tests pass, except for t/op/pack.t​:

not ok 1012
# For list (-2147483648, -1, 0, 1, 2147483647) (total -1) packed with i
unpack '%53i' gave 8589934591, expected 9007199254740991
not ok 1015
# For list (-2147483648, -1, 0, 1, 2147483647) (total -1) packed with i
unpack '%54i' gave 8589934591, expected 18014398509481983
not ok 1018
# For list (-2147483648, -1, 0, 1, 2147483647) (total -1) packed with i
unpack '%63i' gave 8589934591, expected 9223372036854775807
not ok 1021
# For list (-2147483648, -1, 0, 1, 2147483647) (total -1) packed with i
unpack '%64i' gave 8589934591, expected 18446744073709551615
not ok 1024
# For list (-2147483648, -1, 0, 1, 2147483647) (total -1) packed with i
unpack '%65i' gave 8589934591, expected 0
not ok 1067
# For list (-2147483648, -1, 0, 1, 2147483647) (total -1) packed with i>
unpack '%53i>' gave 8589934591, expected 9007199254740991
not ok 1070
# For list (-2147483648, -1, 0, 1, 2147483647) (total -1) packed with i>
unpack '%54i>' gave 8589934591, expected 18014398509481983
not ok 1073
# For list (-2147483648, -1, 0, 1, 2147483647) (total -1) packed with i>
unpack '%63i>' gave 8589934591, expected 9223372036854775807
not ok 1076
# For list (-2147483648, -1, 0, 1, 2147483647) (total -1) packed with i>
unpack '%64i>' gave 8589934591, expected 18446744073709551615
not ok 1079
# For list (-2147483648, -1, 0, 1, 2147483647) (total -1) packed with i>
unpack '%65i>' gave 8589934591, expected 0
not ok 1122
# For list (-2147483648, -1, 0, 1, 2147483647) (total -1) packed with i<
unpack '%53i<' gave 8589934591, expected 9007199254740991
not ok 1125
# For list (-2147483648, -1, 0, 1, 2147483647) (total -1) packed with i<
unpack '%54i<' gave 8589934591, expected 18014398509481983
not ok 1128
# For list (-2147483648, -1, 0, 1, 2147483647) (total -1) packed with i<
unpack '%63i<' gave 8589934591, expected 9223372036854775807
not ok 1131
# For list (-2147483648, -1, 0, 1, 2147483647) (total -1) packed with i<
unpack '%64i<' gave 8589934591, expected 18446744073709551615
not ok 1134
# For list (-2147483648, -1, 0, 1, 2147483647) (total -1) packed with i<
unpack '%65i<' gave 8589934591, expected 0
not ok 1342
# For list (-2147483648, -1, 0, 1, 2147483647) (total -1) packed with l
unpack '%53l' gave 8589934591, expected 9007199254740991
not ok 1345
# For list (-2147483648, -1, 0, 1, 2147483647) (total -1) packed with l
unpack '%54l' gave 8589934591, expected 18014398509481983
not ok 1348
# For list (-2147483648, -1, 0, 1, 2147483647) (total -1) packed with l
unpack '%63l' gave 8589934591, expected 9223372036854775807
not ok 1351
# For list (-2147483648, -1, 0, 1, 2147483647) (total -1) packed with l
unpack '%64l' gave 8589934591, expected 18446744073709551615
not ok 1354
# For list (-2147483648, -1, 0, 1, 2147483647) (total -1) packed with l
unpack '%65l' gave 8589934591, expected 0
not ok 1397
# For list (-2147483648, -1, 0, 1, 2147483647) (total -1) packed with l>
unpack '%53l>' gave 8589934591, expected 9007199254740991
not ok 1400
# For list (-2147483648, -1, 0, 1, 2147483647) (total -1) packed with l>
unpack '%54l>' gave 8589934591, expected 18014398509481983
not ok 1403
# For list (-2147483648, -1, 0, 1, 2147483647) (total -1) packed with l>
unpack '%63l>' gave 8589934591, expected 9223372036854775807
not ok 1406
# For list (-2147483648, -1, 0, 1, 2147483647) (total -1) packed with l>
unpack '%64l>' gave 8589934591, expected 18446744073709551615
not ok 1409
# For list (-2147483648, -1, 0, 1, 2147483647) (total -1) packed with l>
unpack '%65l>' gave 8589934591, expected 0
not ok 1452
# For list (-2147483648, -1, 0, 1, 2147483647) (total -1) packed with l<
unpack '%53l<' gave 8589934591, expected 9007199254740991
not ok 1455
# For list (-2147483648, -1, 0, 1, 2147483647) (total -1) packed with l<
unpack '%54l<' gave 8589934591, expected 18014398509481983
not ok 1458
# For list (-2147483648, -1, 0, 1, 2147483647) (total -1) packed with l<
unpack '%63l<' gave 8589934591, expected 9223372036854775807
not ok 1461
# For list (-2147483648, -1, 0, 1, 2147483647) (total -1) packed with l<
unpack '%64l<' gave 8589934591, expected 18446744073709551615
not ok 1464
# For list (-2147483648, -1, 0, 1, 2147483647) (total -1) packed with l<
unpack '%65l<' gave 8589934591, expected 0
not ok 2002
# For list (-2147483648, -1, 0, 1, 2147483647) (total -1) packed with i!
unpack '%53i!' gave 8589934591, expected 9007199254740991
not ok 2005
# For list (-2147483648, -1, 0, 1, 2147483647) (total -1) packed with i!
unpack '%54i!' gave 8589934591, expected 18014398509481983
not ok 2008
# For list (-2147483648, -1, 0, 1, 2147483647) (total -1) packed with i!
unpack '%63i!' gave 8589934591, expected 9223372036854775807
not ok 2011
# For list (-2147483648, -1, 0, 1, 2147483647) (total -1) packed with i!
unpack '%64i!' gave 8589934591, expected 18446744073709551615
not ok 2014
# For list (-2147483648, -1, 0, 1, 2147483647) (total -1) packed with i!
unpack '%65i!' gave 8589934591, expected 0
not ok 2057
# For list (-2147483648, -1, 0, 1, 2147483647) (total -1) packed with i!>
unpack '%53i!>' gave 8589934591, expected 9007199254740991
not ok 2060
# For list (-2147483648, -1, 0, 1, 2147483647) (total -1) packed with i!>
unpack '%54i!>' gave 8589934591, expected 18014398509481983
not ok 2063
# For list (-2147483648, -1, 0, 1, 2147483647) (total -1) packed with i!>
unpack '%63i!>' gave 8589934591, expected 9223372036854775807
not ok 2066
# For list (-2147483648, -1, 0, 1, 2147483647) (total -1) packed with i!>
unpack '%64i!>' gave 8589934591, expected 18446744073709551615
not ok 2069
# For list (-2147483648, -1, 0, 1, 2147483647) (total -1) packed with i!>
unpack '%65i!>' gave 8589934591, expected 0
not ok 2112
# For list (-2147483648, -1, 0, 1, 2147483647) (total -1) packed with i!<
unpack '%53i!<' gave 8589934591, expected 9007199254740991
not ok 2115
# For list (-2147483648, -1, 0, 1, 2147483647) (total -1) packed with i!<
unpack '%54i!<' gave 8589934591, expected 18014398509481983
not ok 2118
# For list (-2147483648, -1, 0, 1, 2147483647) (total -1) packed with i!<
unpack '%63i!<' gave 8589934591, expected 9223372036854775807
not ok 2121
# For list (-2147483648, -1, 0, 1, 2147483647) (total -1) packed with i!<
unpack '%64i!<' gave 8589934591, expected 18446744073709551615
not ok 2124
# For list (-2147483648, -1, 0, 1, 2147483647) (total -1) packed with i!<
unpack '%65i!<' gave 8589934591, expected 0

Perl Info
-----------------------------------

Flags:
    category=core
    severity=low

Site configuration information for perl 5.16.2:

Configured by hugmeir at Tue Nov 20 17:20:00 ART 2012.

Summary of my perl5 (revision 5 version 16 subversion 2) configuration:

  Platform:
    osname=linux, osvers=3.5.0-18-generic,
archname=x86_64-linux-thread-multi
    uname='linux naw 3.5.0-18-generic #29-ubuntu smp fri oct 19 10:26:51
utc 2012 x86_64 x86_64 x86_64 gnulinux '
    config_args='-de
-Dprefix=/home/hugmeir/perl5/perlbrew/perls/perl-5.16.2 -DDEBUGGING
-Dusethreads -Doptimize=-g -O0 -ggdb3 -Uversiononly -Accflags=-Wall -Wextra
-Aeval:scriptdir=/home/hugmeir/perl5/perlbrew/perls/perl-5.16.2/bin'
    hint=recommended, useposix=true, d_sigaction=define
    useithreads=define, usemultiplicity=define
    useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
    use64bitint=define, use64bitall=define, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='cc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -Wall -Wextra -DDEBUGGING
-fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include
-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    optimize='-g -O0 -ggdb3',
    cppflags='-D_REENTRANT -D_GNU_SOURCE -Wall -Wextra -DDEBUGGING
-fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include'
    ccversion='', gccversion='4.7.2', gccosandvers=''
    intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=12345678
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16
    ivtype='long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t',
lseeksize=8
    alignbytes=8, prototype=define
  Linker and Libraries:
    ld='cc', ldflags =' -fstack-protector -L/usr/local/lib'
    libpth=/usr/local/lib /lib/x86_64-linux-gnu /lib/../lib
/usr/lib/x86_64-linux-gnu /usr/lib/../lib /lib /usr/lib
    libs=-lnsl -ldb -ldl -lm -lcrypt -lutil -lpthread -lc
    perllibs=-lnsl -ldl -lm -lcrypt -lutil -lpthread -lc
    libc=, so=so, useshrplib=false, libperl=libperl.a
    gnulibc_version='2.15'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
    cccdlflags='-fPIC', lddlflags='-shared -g -O0 -ggdb3 -L/usr/local/lib
-fstack-protector'

Locally applied patches:



@INC for perl 5.16.2:
    /home/hugmeir/.perlbrew/libs/perl-5.16.2@all
/lib/perl5/x86_64-linux-thread-multi
    /home/hugmeir/.perlbrew/libs/perl-5.16.2@all/lib/perl5

/home/hugmeir/perl5/perlbrew/perls/perl-5.16.2/lib/site_perl/5.16.2/x86_64-linux-thread-multi
    /home/hugmeir/perl5/perlbrew/perls/perl-5.16.2/lib/site_perl/5.16.2

/home/hugmeir/perl5/perlbrew/perls/perl-5.16.2/lib/5.16.2/x86_64-linux-thread-multi
    /home/hugmeir/perl5/perlbrew/perls/perl-5.16.2/lib/5.16.2
    .


Environment for perl 5.16.2:
    HOME=/home/hugmeir
    LANG=en_US.UTF-8
    LANGUAGE (unset)
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)

PATH=/home/hugmeir/.rbenv/shims:/home/hugmeir/.rbenv/bin:/home/hugmeir/.perlbrew/libs/perl-5.16.2@all
/bin:/home/hugmeir/perl5/perlbrew/bin:/home/hugmeir/perl5/perlbrew/perls/perl-5.16.2/bin:/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
    PERL5LIB=/home/hugmeir/.perlbrew/libs/perl-5.16.2@all/lib/perl5
    PERLBREW_BASHRC_VERSION=0.61
    PERLBREW_HOME=/home/hugmeir/.perlbrew
    PERLBREW_LIB=all
    PERLBREW_MANPATH=/home/hugmeir/.perlbrew/libs/perl-5.16.2@all
/man:/home/hugmeir/perl5/perlbrew/perls/perl-5.16.2/man
    PERLBREW_PATH=/home/hugmeir/.perlbrew/libs/perl-5.16.2@all
/bin:/home/hugmeir/perl5/perlbrew/bin:/home/hugmeir/perl5/perlbrew/perls/perl-5.16.2/bin
    PERLBREW_PERL=perl-5.16.2
    PERLBREW_ROOT=/home/hugmeir/perl5/perlbrew
    PERLBREW_VERSION=0.61
    PERL_BADLANG (unset)
    PERL_LOCAL_LIB_ROOT=/home/hugmeir/.perlbrew/libs/perl-5.16.2@all
    PERL_MB_OPT=--install_base /home/hugmeir/.perlbrew/libs/perl-5.16.2@all
    PERL_MM_OPT=INSTALL_BASE=/home/hugmeir/.perlbrew/libs/perl-5.16.2@all
    SHELL=/bin/bash

@p5pRT
Copy link
Author

p5pRT commented Apr 30, 2013

From @nwc10

On Sat, Apr 06, 2013 at 04​:36​:31AM -0700, Brian Fraser wrote​:

$ opencc --version
Open64 Compiler Suite​: Version 4.5.2.1
Built on​: 2013-04-06 06​:04​:55 -0300
Thread model​: posix
GNU gcc version 4.2.0 (Open64 4.5.2.1 driver)

Which version *is* that?
As best I can work out, there has never been a 4.5 release. 5.0 is current
(Nov 2011), and 4.2.4 was the previous branch​:

http​://www.open64.net/news.html

My configure line is just this​:

./Configure -des -Dusedevel -DDEBUGGING -Dcc=opencc
-Accflags='-OPT​:Olimit=0'

not ok 1012
# For list (-2147483648, -1, 0, 1, 2147483647) (total -1) packed with i
unpack '%53i' gave 8589934591, expected 9007199254740991
not ok 1015
# For list (-2147483648, -1, 0, 1, 2147483647) (total -1) packed with i
unpack '%54i' gave 8589934591, expected 18014398509481983
not ok 1018

Also, this isn't the perl -V from the compiler that you were building with​:

Summary of my perl5 (revision 5 version 16 subversion 2) configuration​:

Platform​:
osname=linux, osvers=3.5.0-18-generic,
archname=x86_64-linux-thread-multi
uname='linux naw 3.5.0-18-generic #29-ubuntu smp fri oct 19 10​:26​:51
utc 2012 x86_64 x86_64 x86_64 gnulinux '
config_args='-de
-Dprefix=/home/hugmeir/perl5/perlbrew/perls/perl-5.16.2 -DDEBUGGING
-Dusethreads -Doptimize=-g -O0 -ggdb3 -Uversiononly -Accflags=-Wall -Wextra
-Aeval​:scriptdir=/home/hugmeir/perl5/perlbrew/perls/perl-5.16.2/bin'
hint=recommended, useposix=true, d_sigaction=define
useithreads=define, usemultiplicity=define
useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
use64bitint=define, use64bitall=define, uselongdouble=undef
usemymalloc=n, bincompat5005=undef
Compiler​:
cc='cc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -Wall -Wextra -DDEBUGGING
-fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include
-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
optimize='-g -O0 -ggdb3',
cppflags='-D_REENTRANT -D_GNU_SOURCE -Wall -Wextra -DDEBUGGING
-fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include'
ccversion='', gccversion='4.7.2', gccosandvers=''

which makes it harder to work out what is going on.

However, I can (eventually) get Open64 to build. I am going to document
this, because the summary conclusion becomes relevant to what to do next.

I first tried to build the current release, 5.0.0, from source from the
tarball, on a 6 month old Ubuntu install on x86_64 linux.

To do this, it seems

1) It insists on building 32 bit, so I have to install the gcc multilibs
  package so that gcc -m32 works
2) As a chunk of it is in C++, I need to install the g++ multilibs packages
3) This *still* doesn't work, as it fails to compile some of the C++ code.
  The default system version of gcc/g++ is 4.7. I've installed 4.8 in
  /usr/local
  The release notes say that they've dropped gcc 3 support, and recommend
  upgrading from that to 4.3. They mention 4.4
  g++-4.4 is the *earliest* version I can install, so I install that.
  This at least gets past that compile problem
4) However, it is still spewing warnings from one g++ supplied header that
  this functionality is deprecated and will be removed without warning
5) It bails out later due to a bad path in a Makefile. I fix this. Why?

$ diff -u osprey-gcc-4.2.0/host-x86_64-redhat-linux/gcc/Makefile~ osprey-gcc-4.2.0/host-x86_64-redhat-linux/gcc/Makefile

Inline Patch
--- osprey-gcc-4.2.0/host-x86_64-redhat-linux/gcc/Makefile~     2013-04-25 20:15:50.000000000 +0200
+++ osprey-gcc-4.2.0/host-x86_64-redhat-linux/gcc/Makefile      2013-04-25 20:28:24.000000000 +0200
@@ -848,7 +848,7 @@
 #LIBGSPIN = ../../../libspin/libgspin42.a
 #This is a symbol link, create by the CONFIGURE script
 #LIBGSPIN = ../../../libspin/libgspin42.a
-LIBGSPIN = ../../osprey/targdir/libspin_4_2_0/libgspin42.a
+LIBGSPIN = ../../../osprey/targdir/libspin_4_2_0/libgspin42.a
 
 # Build and host support libraries.
 LIBIBERTY = ../libiberty/libiberty.a

6) There are still other errors. I spot part of the instructions on the web   page​:

  On some Ubuntu distributions, you need to change the symbol link
  '/bin/sh' to '/bin/bash' to make the scripts work.

  http​://www.open64.net/?id=254

  I do this. It's a good job the power didn't go out in the middle, as
  not having /bin/sh would render the machine unbootable.

  I'd also like to express my utter *contempt* for anything which feels that
  the right "fix" for #! lines that read "/bin/sh" instead of "/bin/bash" is
  to keep the #! lines the same and instead futz with the root filesystem as
  root.
7) This still didn't fix the build.
  So I got trunk from subversion. That does build.

With this, I can replicate your problem.

It seems to be a code generation bug.

With the optimisation level you gave​:

$ ./perl -le 'print unpack "%33i", pack "i", -2147483648
2147483648

One would expect this​:
$ perl -le 'print unpack "%33i", pack "i", -2147483648'
6442450944

If I turn the optimiser down, it goes away.
I wondered if it was bug in our code from abusing C aliasing, but having
tweaked a function to take this didn't seem to be it.

For the example above, it's this bit of pp_pack.c​:

  case 'i' | TYPE_IS_SHRIEKING​:
  while (len-- > 0) {
  int aint;
  SHIFT_VAR(utf8, s, strend, aint, datumtype);
  DO_BO_UNPACK(aint, i);
  if (!checksum)
  mPUSHi(aint);
  else if (checksum > bits_in_uv)
  cdouble += (NV)aint;
  else
  cuv += aint;
  }
  break;

Sticking gdb on there to look at aint produces garbage​:

(gdb)
1822 SHIFT_VAR(utf8, s, strend, aint, datumtype);
(gdb)
1823 DO_BO_UNPACK(aint, i);
(gdb) p aint
$1 = 7123920
(gdb) s
1824 if (!checksum)
(gdb)
1826 else if (checksum > bits_in_uv)
(gdb)
1829 cuv += aint;
(gdb) p aint
$2 = 7123920
(gdb) s
1820 while (len-- > 0) {
(gdb) p cuv
$3 = 2147483648

However, as it's compiled with -O2 as well as -g, it's not clear whether this
is just an artefact of buggy debugging metadata generated by the compiler.

So I stuck a printf() in there, and the bug goes away.

Interesting.

Question - is this because printf() is varargs, and so it forces that variable
aint to be stored on the stack? Or is it something else?

After a bit of experimentation, it seemed that adding any *reference* to
aint between SHIFT_VAR() and DO_BO_UNPACK() makes the bug go away. So,
there is no bug with this​:

Inline Patch
diff --git a/pp_pack.c b/pp_pack.c
index eaeec89..33a65b6 100644
--- a/pp_pack.c
+++ b/pp_pack.c
@@ -1820,6 +1820,8 @@ S_unpack_rec(pTHX_ tempsym_t* symptr, const char *s, const
            while (len-- > 0) {
                int aint;
                SHIFT_VAR(utf8, s, strend, aint, datumtype);
+                if (aint)
+                    getpid();
                DO_BO_UNPACK(aint, i);
                if (!checksum)
                    mPUSHi(aint);


but the bug is still visible with this:
Inline Patch
diff --git a/pp_pack.c b/pp_pack.c
index eaeec89..3366c59 100644
--- a/pp_pack.c
+++ b/pp_pack.c
@@ -1820,6 +1820,8 @@ S_unpack_rec(pTHX_ tempsym_t* symptr, const char *s, const
            while (len-- > 0) {
                int aint;
                SHIFT_VAR(utf8, s, strend, aint, datumtype);
+                if (checksum)
+                    getpid();
                DO_BO_UNPACK(aint, i);
                if (!checksum)
                    mPUSHi(aint);



The generated assembly code for the two is very close:

$ diff -u pp_pack.s.bad pp_pack.s.good | diffstat
pp_pack.s.good | 37 +++++++++++++++++++------------------
1 file changed, 19 insertions(+), 18 deletions(-)

I don't know x86_64 assembler (and there isn't space in my head for it)
but the diff is small enough to experiment with by trial and error to find
the solution. This appears to be the fix needed to the assembler​:

$ diff -u pp_pack.s.bad pp_pack.s

Inline Patch
--- pp_pack.s.bad       2013-04-26 16:49:40.000000000 +0200
+++ pp_pack.s   2013-04-26 16:51:29.000000000 +0200
@@ -9416,7 +9416,8 @@
  #<loop> Part of loop body line 1822, head labeled .Lt_68_360194
        .loc    1       1831    0
        movq -464(%rbp),%rax            # [0] cuv
-       addq %rsi,%rax                  # [3] 
+       movslq %esi,%rdi                # [2] 
+       addq %rdi,%rax                  # [3] 
        movq %rax,-464(%rbp)            # [4] cuv
        jmp .Lt_68_425730               # [4] 
 .LBB426_S_unpack_rec:

With that there is no bug (for 'i'. I assume that the others are the same)

So, yes, I think that this is a compiler bug. In theory we could try to
work round this.

In practise, I don't think that we should bother

1) It's not obvious how to to do it cleanly
2) I don't think that it's worth it. The Open64 compiler doesn't look like
  it has much future. However good its codegen might be, it doesn't look
  like it will survive against gcc and clang.

  There aren't many commits since 2011, and if they aren't careful they will
  die when their C++ code no longer compiles on supported, installable g++
  releases.

3) That code in pp_pack.c is a lot more complex than it could be. In
  particular, I think that the jobs of SHIFT_VAR() and DO_BO_UNPACK() should
  be merged and reworked. At which point the code will be considerably
  different (and simpler), which might mean that the bug is never hit.

SHIFT_VAR() is from Ton Hospel's "encoding neutral unpack" work. It either
uses Copy() to copy bytes to the target variable, or calls out to a function
to decode UTF-8 if the source string is in UTF-8.

DO_BO_UNPACK() is from Marcus Holland Moritz's byte-order changes. It flips
the endianness if a suffix is used.

I think that the byte-order stuff was done first.

Right now, the code carefully copies (logical) characters in-order into an
integer variable aint, and then (if necessary) carefully uses bit-shifting
to invert that integer variable.

I think that a simpler solution would be to migrate that inversion into the
"copy" routine. Reverse the bytes while copying them, if an endian-swap is
needed. Keep the inline Copy() for the case of source is octets, no endian
swap, and push the other 3 cases into the helper function. That way the
default path remains fast and small, and a lot of inline code is
de-duplicated.

However, I can see that that refactoring is going to be a little
involved.

I guess that this bug is sort of a "wontfix".

Nicholas Clark

@p5pRT
Copy link
Author

p5pRT commented Apr 30, 2013

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Apr 30, 2013

@nwc10 - Status changed from 'open' to 'stalled'

@p5pRT
Copy link
Author

p5pRT commented Apr 30, 2013

From @Hugmeir

On Tue, Apr 30, 2013 at 9​:36 AM, Nicholas Clark <nick@​ccl4.org> wrote​:

On Sat, Apr 06, 2013 at 04​:36​:31AM -0700, Brian Fraser wrote​:

$ opencc --version
Open64 Compiler Suite​: Version 4.5.2.1
Built on​: 2013-04-06 06​:04​:55 -0300
Thread model​: posix
GNU gcc version 4.2.0 (Open64 4.5.2.1 driver)

Which version *is* that?
As best I can work out, there has never been a 4.5 release. 5.0 is current
(Nov 2011), and 4.2.4 was the previous branch​:

http​://www.open64.net/news.html

http​://developer.amd.com/tools-and-sdks/cpu-development/x86-open64-compiler-suite/

My configure line is just this​:

./Configure -des -Dusedevel -DDEBUGGING -Dcc=opencc
-Accflags='-OPT​:Olimit=0'

not ok 1012
# For list (-2147483648, -1, 0, 1, 2147483647) (total -1) packed with i
unpack '%53i' gave 8589934591, expected 9007199254740991
not ok 1015
# For list (-2147483648, -1, 0, 1, 2147483647) (total -1) packed with i
unpack '%54i' gave 8589934591, expected 18014398509481983
not ok 1018

Also, this isn't the perl -V from the compiler that you were building with​:

Oh, I apologize. IIRC I was building with "blead as of today",
so c1789b9 or thereabouts.

Summary of my perl5 (revision 5 version 16 subversion 2) configuration​:

Platform​:
osname=linux, osvers=3.5.0-18-generic,
archname=x86_64-linux-thread-multi
uname='linux naw 3.5.0-18-generic #29-ubuntu smp fri oct 19 10​:26​:51
utc 2012 x86_64 x86_64 x86_64 gnulinux '
config_args='-de
-Dprefix=/home/hugmeir/perl5/perlbrew/perls/perl-5.16.2 -DDEBUGGING
-Dusethreads -Doptimize=-g -O0 -ggdb3 -Uversiononly -Accflags=-Wall
-Wextra
-Aeval​:scriptdir=/home/hugmeir/perl5/perlbrew/perls/perl-5.16.2/bin'
hint=recommended, useposix=true, d_sigaction=define
useithreads=define, usemultiplicity=define
useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
use64bitint=define, use64bitall=define, uselongdouble=undef
usemymalloc=n, bincompat5005=undef
Compiler​:
cc='cc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -Wall -Wextra
-DDEBUGGING
-fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include
-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
optimize='-g -O0 -ggdb3',
cppflags='-D_REENTRANT -D_GNU_SOURCE -Wall -Wextra -DDEBUGGING
-fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include'
ccversion='', gccversion='4.7.2', gccosandvers=''

which makes it harder to work out what is going on.

However, I can (eventually) get Open64 to build. I am going to document
this, because the summary conclusion becomes relevant to what to do next.

I first tried to build the current release, 5.0.0, from source from the
tarball, on a 6 month old Ubuntu install on x86_64 linux.

Hm... My experience was also troublesome, but nowhere as annoying as all of
this. I had to change that file and remove a line from another, and install
some fortran stuff for gcc, but after that it compiled without issues.

To do this, it seems

1) It insists on building 32 bit, so I have to install the gcc multilibs
package so that gcc -m32 works
2) As a chunk of it is in C++, I need to install the g++ multilibs packages
3) This *still* doesn't work, as it fails to compile some of the C++ code.
The default system version of gcc/g++ is 4.7. I've installed 4.8 in
/usr/local
The release notes say that they've dropped gcc 3 support, and recommend
upgrading from that to 4.3. They mention 4.4
g++-4.4 is the *earliest* version I can install, so I install that.
This at least gets past that compile problem
4) However, it is still spewing warnings from one g++ supplied header that
this functionality is deprecated and will be removed without warning
5) It bails out later due to a bad path in a Makefile. I fix this. Why?

$ diff -u osprey-gcc-4.2.0/host-x86_64-redhat-linux/gcc/Makefile~
osprey-gcc-4.2.0/host-x86_64-redhat-linux/gcc/Makefile
--- osprey-gcc-4.2.0/host-x86_64-redhat-linux/gcc/Makefile~ 2013-04-25
20​:15​:50.000000000 +0200
+++ osprey-gcc-4.2.0/host-x86_64-redhat-linux/gcc/Makefile 2013-04-25
20​:28​:24.000000000 +0200
@​@​ -848,7 +848,7 @​@​
#LIBGSPIN = ../../../libspin/libgspin42.a
#This is a symbol link, create by the CONFIGURE script
#LIBGSPIN = ../../../libspin/libgspin42.a
-LIBGSPIN = ../../osprey/targdir/libspin_4_2_0/libgspin42.a
+LIBGSPIN = ../../../osprey/targdir/libspin_4_2_0/libgspin42.a

# Build and host support libraries.
LIBIBERTY = ../libiberty/libiberty.a

6) There are still other errors. I spot part of the instructions on the web
page​:

    On some Ubuntu distributions\, you need to change the symbol link
    '/bin/sh' to '/bin/bash' to make the scripts work\.

http​://www.open64.net/?id=254

I do this. It's a good job the power didn't go out in the middle, as
not having /bin/sh would render the machine unbootable.

I'd also like to express my utter *contempt* for anything which feels
that
the right "fix" for #! lines that read "/bin/sh" instead of "/bin/bash"
is
to keep the #! lines the same and instead futz with the root filesystem
as
root.
7) This still didn't fix the build.
So I got trunk from subversion. That does build.

With this, I can replicate your problem.

It seems to be a code generation bug.

With the optimisation level you gave​:

$ ./perl -le 'print unpack "%33i", pack "i", -2147483648
2147483648

One would expect this​:
$ perl -le 'print unpack "%33i", pack "i", -2147483648'
6442450944

If I turn the optimiser down, it goes away.
I wondered if it was bug in our code from abusing C aliasing, but having
tweaked a function to take this didn't seem to be it.

For the example above, it's this bit of pp_pack.c​:

    case 'i' | TYPE\_IS\_SHRIEKING&#8203;:
        while \(len\-\- > 0\) \{
            int aint;
            SHIFT\_VAR\(utf8\, s\, strend\, aint\, datumtype\);
            DO\_BO\_UNPACK\(aint\, i\);
            if \(\!checksum\)
                mPUSHi\(aint\);
            else if \(checksum > bits\_in\_uv\)
                cdouble \+= \(NV\)aint;
            else
                cuv \+= aint;
        \}
        break;

Sticking gdb on there to look at aint produces garbage​:

(gdb)
1822 SHIFT_VAR(utf8, s, strend, aint, datumtype);
(gdb)
1823 DO_BO_UNPACK(aint, i);
(gdb) p aint
$1 = 7123920
(gdb) s
1824 if (!checksum)
(gdb)
1826 else if (checksum > bits_in_uv)
(gdb)
1829 cuv += aint;
(gdb) p aint
$2 = 7123920
(gdb) s
1820 while (len-- > 0) {
(gdb) p cuv
$3 = 2147483648

However, as it's compiled with -O2 as well as -g, it's not clear whether
this
is just an artefact of buggy debugging metadata generated by the compiler.

So I stuck a printf() in there, and the bug goes away.

Interesting.

Question - is this because printf() is varargs, and so it forces that
variable
aint to be stored on the stack? Or is it something else?

After a bit of experimentation, it seemed that adding any *reference* to
aint between SHIFT_VAR() and DO_BO_UNPACK() makes the bug go away. So,
there is no bug with this​:

diff --git a/pp_pack.c b/pp_pack.c
index eaeec89..33a65b6 100644
--- a/pp_pack.c
+++ b/pp_pack.c
@​@​ -1820,6 +1820,8 @​@​ S_unpack_rec(pTHX_ tempsym_t* symptr, const char *s,
const
while (len-- > 0) {
int aint;
SHIFT_VAR(utf8, s, strend, aint, datumtype);
+ if (aint)
+ getpid();
DO_BO_UNPACK(aint, i);
if (!checksum)
mPUSHi(aint);

but the bug is still visible with this​:

diff --git a/pp_pack.c b/pp_pack.c
index eaeec89..3366c59 100644
--- a/pp_pack.c
+++ b/pp_pack.c
@​@​ -1820,6 +1820,8 @​@​ S_unpack_rec(pTHX_ tempsym_t* symptr, const char *s,
const
while (len-- > 0) {
int aint;
SHIFT_VAR(utf8, s, strend, aint, datumtype);
+ if (checksum)
+ getpid();
DO_BO_UNPACK(aint, i);
if (!checksum)
mPUSHi(aint);

The generated assembly code for the two is very close​:

$ diff -u pp_pack.s.bad pp_pack.s.good | diffstat
pp_pack.s.good | 37 +++++++++++++++++++------------------
1 file changed, 19 insertions(+), 18 deletions(-)

I don't know x86_64 assembler (and there isn't space in my head for it)
but the diff is small enough to experiment with by trial and error to find
the solution. This appears to be the fix needed to the assembler​:

$ diff -u pp_pack.s.bad pp_pack.s
--- pp_pack.s.bad 2013-04-26 16​:49​:40.000000000 +0200
+++ pp_pack.s 2013-04-26 16​:51​:29.000000000 +0200
@​@​ -9416,7 +9416,8 @​@​
#<loop> Part of loop body line 1822, head labeled .Lt_68_360194
.loc 1 1831 0
movq -464(%rbp),%rax # [0] cuv
- addq %rsi,%rax # [3]
+ movslq %esi,%rdi # [2]
+ addq %rdi,%rax # [3]
movq %rax,-464(%rbp) # [4] cuv
jmp .Lt_68_425730 # [4]
.LBB426_S_unpack_rec​:

With that there is no bug (for 'i'. I assume that the others are the same)

So, yes, I think that this is a compiler bug. In theory we could try to
work round this.

In practise, I don't think that we should bother

1) It's not obvious how to to do it cleanly
2) I don't think that it's worth it. The Open64 compiler doesn't look like
it has much future. However good its codegen might be, it doesn't look
like it will survive against gcc and clang.

There aren't many commits since 2011, and if they aren't careful they
will
die when their C++ code no longer compiles on supported, installable g++
releases.

3) That code in pp_pack.c is a lot more complex than it could be. In
particular, I think that the jobs of SHIFT_VAR() and DO_BO_UNPACK()
should
be merged and reworked. At which point the code will be considerably
different (and simpler), which might mean that the bug is never hit.

SHIFT_VAR() is from Ton Hospel's "encoding neutral unpack" work. It either
uses Copy() to copy bytes to the target variable, or calls out to a
function
to decode UTF-8 if the source string is in UTF-8.

DO_BO_UNPACK() is from Marcus Holland Moritz's byte-order changes. It flips
the endianness if a suffix is used.

I think that the byte-order stuff was done first.

Right now, the code carefully copies (logical) characters in-order into an
integer variable aint, and then (if necessary) carefully uses bit-shifting
to invert that integer variable.

I think that a simpler solution would be to migrate that inversion into the
"copy" routine. Reverse the bytes while copying them, if an endian-swap is
needed. Keep the inline Copy() for the case of source is octets, no endian
swap, and push the other 3 cases into the helper function. That way the
default path remains fast and small, and a lot of inline code is
de-duplicated.

However, I can see that that refactoring is going to be a little
involved.

I guess that this bug is sort of a "wontfix".

Most of this is beyond me for now, but +1 to the conclusion. Thank you for
the detective work!

@p5pRT
Copy link
Author

p5pRT commented Apr 30, 2013

The RT System itself - Status changed from 'stalled' to 'open'

@p5pRT
Copy link
Author

p5pRT commented May 3, 2013

From @nwc10

On Tue, Apr 30, 2013 at 03​:49​:51PM -0300, Brian Fraser wrote​:

On Tue, Apr 30, 2013 at 9​:36 AM, Nicholas Clark <nick@​ccl4.org> wrote​:

On Sat, Apr 06, 2013 at 04​:36​:31AM -0700, Brian Fraser wrote​:

$ opencc --version
Open64 Compiler Suite​: Version 4.5.2.1
Built on​: 2013-04-06 06​:04​:55 -0300
Thread model​: posix
GNU gcc version 4.2.0 (Open64 4.5.2.1 driver)

Which version *is* that?
As best I can work out, there has never been a 4.5 release. 5.0 is current
(Nov 2011), and 4.2.4 was the previous branch​:

http​://www.open64.net/news.html

http​://developer.amd.com/tools-and-sdks/cpu-development/x86-open64-compiler-suite/

Oh, interesting. So which one is the fork? :-)

That looks like a compiler with more of a future than the open64.net version.

I first tried to build the current release, 5.0.0, from source from the
tarball, on a 6 month old Ubuntu install on x86_64 linux.

Hm... My experience was also troublesome, but nowhere as annoying as all of
this. I had to change that file and remove a line from another, and install
some fortran stuff for gcc, but after that it compiled without issues.

I infer that this is because we were using versions from different alternate
realities. The one where "5" never happened looks to be more useful.

It's not obvious how to reduce pp_pack.c down to any sort of test case that
a compiler writer could use.

I hope that a refactoring of pp_pack.c (with the side effect of making it
clearer and hopefully smaller) would avoid hitting the bug.

Nicholas Clark

@p5pRT
Copy link
Author

p5pRT commented May 9, 2013

From @nwc10

On Fri, May 03, 2013 at 12​:32​:54PM +0100, Nicholas Clark wrote​:

I infer that this is because we were using versions from different alternate
realities. The one where "5" never happened looks to be more useful.

It's not obvious how to reduce pp_pack.c down to any sort of test case that
a compiler writer could use.

I hope that a refactoring of pp_pack.c (with the side effect of making it
clearer and hopefully smaller) would avoid hitting the bug.

The branch has rather diverged from its name, but for me
smoke-me/nicholas/genpacksizetables does build with the Open64 compiler
without showing this error.

(The branch also removes about 1000 lines of source, and reduces the object
size for me with gcc -Os by about 2.5K. With no test changes and I believe
no behaviour changes.)

Nicholas Clark

@p5pRT
Copy link
Author

p5pRT commented May 22, 2013

From @nwc10

On Thu May 09 11​:32​:08 2013, nicholas wrote​:

The branch has rather diverged from its name, but for me
smoke-me/nicholas/genpacksizetables does build with the Open64
compiler
without showing this error.

(The branch also removes about 1000 lines of source, and reduces the
object
size for me with gcc -Os by about 2.5K. With no test changes and I
believe
no behaviour changes.)

This is now merged to blead. Please could you check that blead
builds for you without problems.

Nicholas Clark

@p5pRT
Copy link
Author

p5pRT commented May 22, 2013

From @Hugmeir

On Wed, May 22, 2013 at 7​:13 AM, Nicholas Clark via RT <
perlbug-followup@​perl.org> wrote​:

On Thu May 09 11​:32​:08 2013, nicholas wrote​:

The branch has rather diverged from its name, but for me
smoke-me/nicholas/genpacksizetables does build with the Open64
compiler
without showing this error.

(The branch also removes about 1000 lines of source, and reduces the
object
size for me with gcc -Os by about 2.5K. With no test changes and I
believe
no behaviour changes.)

This is now merged to blead. Please could you check that blead
builds for you without problems.

Nicholas Clark

$ ./TEST op/pack.t
t/op/pack ... ok
All tests successful.
u=0.08 s=0.00 cu=0.30 cs=0.00 scripts=1 tests=14704

Nicholas++

@p5pRT
Copy link
Author

p5pRT commented May 22, 2013

From @nwc10

On Wed May 22 05​:14​:32 2013, Hugmeir wrote​:

On Wed, May 22, 2013 at 7​:13 AM, Nicholas Clark via RT <
perlbug-followup@​perl.org> wrote​:

This is now merged to blead. Please could you check that blead
builds for you without problems.

Nicholas Clark

$ ./TEST op/pack.t
t/op/pack ... ok
All tests successful.
u=0.08 s=0.00 cu=0.30 cs=0.00 scripts=1 tests=14704

Nicholas++

Thanks. Marking this ticket "resolved" as we don't (yet) have a
"fixed, pending release" status.

Nicholas Clark

@p5pRT
Copy link
Author

p5pRT commented May 22, 2013

@nwc10 - Status changed from 'open' to 'resolved'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant