This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug target/29319] ICE unrecognizable insn: offset too large for larl (breaks glibc)



------- Comment #2 from matz at gcc dot gnu dot org  2006-10-02 11:35 -------
Note that with this patch solves the bug for this testcase, but it still
doesn't help with the general case.  With this slightly changed testcase:

% cat large-ofs2.c
static char l_info[100];
void bug1 (unsigned long tag)
{
  char *info = l_info;
  info[tag - 0x100000000 + 1] = 1;
}
void bug2 (unsigned long tag)
{
  char *info = l_info;
  info[tag - 0x100000000 + 1] = 2;
}
extern void abort();
int main()
{
  unsigned i;
  for (i = 0; i < sizeof(l_info); i++)
    l_info[i] = 0;
  bug1(0x100000000);
  bug2(0x100000000);
  if (l_info[2] != 2 || l_info[1] != 1)
    abort();
  return 0;
}

% gcc -S -O2 -fPIC -march=z9-109 large-ofs2.c
% gcc large-ofs2.s
large-ofs2.s: Assembler messages:
large-ofs2.s:19: Error: value of -4294967312 too large for field of 4 bytes at
18

Note how the bodies of both functions is exactly the same, but still it
only fails in the second function.  For reference here the asm of both
functions:

     6  bug1:
     7  .LFB2:
     8          larl    %r1,l_info-4294967296
     9          lhi     %r3,1
    10          stc     %r3,1(%r2,%r1)
    11          br      %r14
    12  .LFE2:
    13          .size   bug1, .-bug1
    14          .align  4
    15  .globl bug2
    16          .type   bug2, @function
    17  bug2:
    18  .LFB3:
    19          larl    %r1,l_info-4294967296
    20          lhi     %r3,2
    21          stc     %r3,1(%r2,%r1)
    22          br      %r14

I assume the reason is, that the assembler somehow calculates this pc
relative.  In that case it could also break later during linking if the
linker doesn't have special means to fix up too large offsets.

So, I think s390x is in the same situation as x86-64.  We can't allow
large constant offsets on objects, even though instructions might accept
them, because the object might become placed just a bit too far away,
so that it's base is still in reach, while the offset added to it is not
anymore.  On x86-64 we solve that by artificially constraining the range
of offsets.  That should perhaps be done here too.  E.g. by using
DISP_IN_RANGE instead of the </>= test I copied from larl_operand.

Up to the maintainers.


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29319


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]