Question about strange register calling truncates to SImode on x86_64
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
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
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
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
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
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.