Question about strange register calling truncates to SImode on x86_64

2006-10-10 Thread Kai Tietz
Hello,

I am currently on to build the gcc target support for x86_64-pc-mingw64. 
While this porting I found a strange register truncation, I do not believe 
it is valid. For the c code:

int foo(char *,...);
int doo(char *h) { return foo("abc ",h); }

compiled result ->

.file   ""
 doo.section .rdata,"dr"
LC0:
.ascii "abc \0"
.text
.globl _doo
.def_doo;   .scl2;  .type   32; .endef
_doo:
LFB2:
pushq   %rbp
LCFI0:
movq%rsp, %rbp
LCFI1:
subq$16, %rsp
LCFI2:
movq%rcx, -8(%rbp)
movq-8(%rbp), %rdx
movl$LC0, %ecx
movl$0, %eax
call_foo
...

It leads to a symbol ref to "abc", which is passed to function foo on 
calling via a 32 bit register. This behaviour seems to be wrong, because 
if the base adress of the code segment gets out-side of 2^32 the 
relocation will be incorrect for sure. May somebody can help if my 
thoughts are wrong or not ...

Regards,
 i.A. Kai Tietz



Re: Question about strange register calling truncates to SImode on x86_64

2006-10-10 Thread Andrew Haley
Kai Tietz writes:

 > I am currently on to build the gcc target support for x86_64-pc-mingw64. 
 > While this porting I found a strange register truncation, I do not believe 
 > it is valid. For the c code:
 > 
 > int foo(char *,...);
 > int doo(char *h) { return foo("abc ",h); }
 > 
 > compiled result ->
 > 
 > .file   ""
 >  doo.section .rdata,"dr"
 > LC0:
 > .ascii "abc \0"
 > .text
 > .globl _doo
 > .def_doo;   .scl2;  .type   32; .endef
 > _doo:
 > LFB2:
 > pushq   %rbp
 > LCFI0:
 > movq%rsp, %rbp
 > LCFI1:
 > subq$16, %rsp
 > LCFI2:
 > movq%rcx, -8(%rbp)
 > movq-8(%rbp), %rdx
 > movl$LC0, %ecx
 > movl$0, %eax
 > call_foo
 > ...
 > 
 > It leads to a symbol ref to "abc", which is passed to function foo on 
 > calling via a 32 bit register. This behaviour seems to be wrong, because 
 > if the base adress of the code segment gets out-side of 2^32 the 
 > relocation will be incorrect for sure. May somebody can help if my 
 > thoughts are wrong or not ...

There's nothing strange about it, it's the default with the small code
model.  Here's the doc:

`-mcmodel=small'
 Generate code for the small code model: the program and its
 symbols must be linked in the lower 2 GB of the address space.
 Pointers are 64 bits.  Programs can be statically or dynamically
 linked.  This is the default code model.

`-mcmodel=kernel'
 Generate code for the kernel code model.  The kernel runs in the
 negative 2 GB of the address space.  This model has to be used for
 Linux kernel code.

`-mcmodel=medium'
 Generate code for the medium model: The program is linked in the
 lower 2 GB of the address space but symbols can be located
 anywhere in the address space.  Programs can be statically or
 dynamically linked, but building of shared libraries are not
 supported with the medium model.

`-mcmodel=large'
 Generate code for the large model: This model makes no assumptions
 about addresses and sizes of sections.  Currently GCC does not
 implement this model.

Andrew.



Re: Question about strange register calling truncates to SImode on x86_64

2006-10-11 Thread Kai Tietz
Hello Andrew,

> -mcmodel=small'
>   Generate code for the small code model: the program and its
>   symbols must be linked in the lower 2 GB of the address space.
>   Pointers are 64 bits.  Programs can be statically or dynamically
>   linked.  This is the default code model.

You are right, the documentation I read, too. But as described even for 
the small-model pointers are 64-bit and are treated beside the argument 
passing via register  correctly. The problem is that a function just set 
the lower 32-bit of the register, but the method using this register as 
argument uses the 64-bit register variant, which means the upper 32-bit of 
the register have random values..

E.g: The c code
int foo(const char *h,int n) { n+=(int) *h; return n; }
int doo(int n) { return foo("abc ",n); }

Leads to the assembly on x86_64 (small)

.file   "test.c"
.text
.globl _foo
.def_foo;   .scl2;  .type   32; .endef
_foo:
LFB2:
pushq   %rbp
LCFI0:
movq%rsp, %rbp
LCFI1:
movq%rcx, -8(%rbp)
movl%edx, -12(%rbp)
movq-8(%rbp), %rax
movzbl  (%rax), %eax
movsbl  %al,%eax
addl%eax, -12(%rbp)
movl-12(%rbp), %eax
leave
ret
LFE2:
.section .rdata,"dr"
LC0:
.ascii "abc \0"
.text
.globl _doo
.def_doo;   .scl2;  .type   32; .endef
_doo:
LFB3:
pushq   %rbp
LCFI2:
movq%rsp, %rbp
LCFI3:
subq$8, %rsp
LCFI4:
movl%ecx, -4(%rbp)
movl-4(%rbp), %edx
movl$LC0, %ecx
call_foo
leave
ret
...

You see, that function "doo" passes the symbolRef LC0 via ecx to function 
foo. But function "foo" uses as input argument rcx for the pointer.

I think the definition of  in i386.md is the reason for this incorrect 
behaviour. I sent a small patch which seems to solve this problem quite 
well without side-effect.


Regards,
 i.A. Kai Tietz

--- gcc-4-2-20060930_org/gcc-4.2-20060930/gcc/config/i386/i386.md 
2006-09-07 19:53:18.0 +0200
+++ gcc-4.2-20060930/gcc/config/i386/i386.md2006-10-11 
09:44:36.610866100 +0200
@@ -2008,9 +2008,7 @@
   return "lea{q}\t{%a1, %0|%0, %a1}";
 default:
   gcc_assert (!flag_pic || LEGITIMATE_PIC_OPERAND_P (operands[1]));
-  if (get_attr_mode (insn) == MODE_SI)
-   return "mov{l}\t{%k1, %k0|%k0, %k1}";
-  else if (which_alternative == 2)
+  if (which_alternative == 2)
return "movabs{q}\t{%1, %0|%0, %1}";
   else
return "mov{q}\t{%1, %0|%0, %1}";


Re: Question about strange register calling truncates to SImode on x86_64

2006-10-11 Thread Michael Matz
Hi,

On Wed, 11 Oct 2006, Kai Tietz wrote:

> > -mcmodel=small'
> >   Generate code for the small code model: the program and its
> >   symbols must be linked in the lower 2 GB of the address space.
> >   Pointers are 64 bits.  Programs can be statically or dynamically
> >   linked.  This is the default code model.
> 
> You are right, the documentation I read, too. But as described even for 
> the small-model pointers are 64-bit and are treated beside the argument 
> passing via register  correctly. The problem is that a function just set 
> the lower 32-bit of the register, but the method using this register as 
> argument uses the 64-bit register variant, which means the upper 32-bit of 
> the register have random values..

No.  The x86-64 instructions which set a 32bit register implicitely zero 
out the upper 32bit.  This is in difference to those operating on the 16 
or 8bit parts, which leave the upper parts untouched.  So this code 
actually sets $rcx to [0, (uint32)&.LC0]

As you are compiling for the small model it's required that &.LC0 == 
(uint32)&.LC0, because it's static data.

And yes, this means that small code model executables have to have a base 
address < 2GB.  This is in difference to the small PIC model, where the 
overall range of all static program addresses must be < 2GB.


Ciao,
Michael.


Re: Question about strange register calling truncates to SImode on x86_64

2006-10-12 Thread Kai Tietz
Hello Michael,

thanks for description. I wasn't aware, that the upper 32 bits are zeroed. 
Does this means that even the stack has to be in the first 4 Gb, too. Or 
does this mov instruction does a sign-extention. 

Best regards,
 i.A. Kai Tietz



Re: Question about strange register calling truncates to SImode on x86_64

2006-10-12 Thread Michael Matz
Hi,

On Thu, 12 Oct 2006, Kai Tietz wrote:

> thanks for description. I wasn't aware, that the upper 32 bits are 
> zeroed. Does this means that even the stack has to be in the first 4 Gb, 
> too.

Why should it?  I.e. no, it doesn't have to.

> Or does this mov instruction does a sign-extention.

Which mov instruction?


Ciao,
Michael.