[llvm-dev] question about ARM 32 big endian

John Brawn via llvm-dev llvm-dev at lists.llvm.org
Fri Jun 17 06:18:53 PDT 2016


Structs are passed as if loaded from memory by an LDM instruction, and
main is doing that correctly. The problem is in how f is then extracting
the elements from that value.

It looks like this is specifically a bug in clang's handling of va_arg -
if you change f to take a struct tiny instead of a variadic list then it
behaves correctly.

Looking at the -O0 emit-llvm output of clang the va_arg is generated as

  %0 = bitcast %struct.__va_list* %ap to i8**
  %argp.cur = load i8*, i8** %0, align 4
  %argp.next = getelementptr inbounds i8, i8* %argp.cur, i32 4
  store i8* %argp.next, i8** %0, align 4
  %1 = getelementptr inbounds i8, i8* %argp.cur, i32 1
  %2 = bitcast i8* %1 to %struct.tiny*
  %3 = bitcast %struct.tiny* %x to i8*
  %4 = bitcast %struct.tiny* %2 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i32(i8* %3, i8* %4, i32 3, i32 1, i1 false)

It's that '%1 = getelementptr inbounds i8, i8* %argp.cur, i32 1' which is
wrong: the offset should be 0 not 1.

John

> -----Original Message-----
> From: llvm-dev [mailto:llvm-dev-bounces at lists.llvm.org] On Behalf Of
> Strahinja Petrovic via llvm-dev
> Sent: 17 June 2016 11:22
> To: llvm-dev at lists.llvm.org
> Subject: [llvm-dev] question about ARM 32 big endian
> 
> Hi everyone,
> 
> I have a question about ARM 32 big endian calling convention. It's about
> sending small structures as function argument.
> For example if passing 3 chars in a structure should alignment in
> register (argument register for passing those chars in function) be
> right-adjusted ?
> LLVM (trunk version) is passing those chars left-adjusted in register,
> and trying to read them  like they are right-adjusted and there is a
> problem.
> GCC is passing chars in register left-adjusted and works properly.
> 
> Here is the example:
> 
> #include <stdarg.h>
> 
> struct tiny
> {
>    char c;
>    char d;
>    char e;
> };
> 
> f (int n, ...)
> {
>    struct tiny x;
> 
>    va_list ap;
>    va_start (ap,n);
>    x = va_arg (ap,struct tiny);
>    if (x.c !=  10)
>        abort();
>    if (x.d !=  11)
>        abort();
>    if(x.e != 12)
>      abort();
>    va_end (ap);
> }
> main ()
> {
>    struct tiny x[3];
>    x[0].c = 10;
>    x[0].d = 11;
>    x[0].e = 12;
>    f (3, x[0]);
>    exit(0);
> }
> 
> 
> 
> _______________________________________________
> LLVM Developers mailing list
> llvm-dev at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev


More information about the llvm-dev mailing list