[LLVMdev] cross compiling with the C backend

Kevin André
Tue, 19 Feb 2008 14:54:01 -0000

On Feb 19, 2008 12:48 AM, Nick Lewycky <nicholas at mxc.ca> wrote:

> No, it's not portable like that. Here's what goes on.
>
> C is portable in the sense that it gives you enough tools to inspect
> your environment. So an 'int' might be any number of chars (which
> themselves may be any number of bits >= 8), but that's okay because
C
> provides 'sizeof(int)'. If you have code like "char *x >
malloc(sizeof(int));" you're going to get different LLVM bytecode
> depending on what platform your llvm-gcc is set to.
>
> LLVM is portable in the sense that the bytecode will behave the same way
> on every platform. So if the above code becomes "%x_addr = malloc
i32"
> then you get a 32-bit integer regardless of the abilities of the
> underlying system.

This is what I thought as well, but I remember reading something that
said you could use the C backend for architectures that do not have a
'real' codegenerator for LLVM yet.

> Finally, the C backend's output isn't portable in the sense that it
uses
> GCC extensions to get the correct output. Which is fine so long as
> you're compiling its output with GCC.

... which is the case here.

> Building llvm-gcc as a cross-compiler would help, if there's a platform
> you can select that matches the PSP more closely.

I did some testing and it seems that my native gcc already is similar
enough. I compiled the following statements:

	printf("     sizeof(char) = %i\n", sizeof(char));
	printf("    sizeof(char*) = %i\n", sizeof(char*));
	printf("    sizeof(void*) = %i\n", sizeof(void*));
	printf("      sizeof(int) = %i\n", sizeof(int));
	printf(" sizeof(unsigned) = %i\n", sizeof(unsigned));
	printf("    sizeof(short) = %i\n", sizeof(short));
	printf("    sizeof(float) = %i\n", sizeof(float));
	printf("   sizeof(double) = %i\n", sizeof(double));
	printf(" endianness = %s\n", htonl(123) == 123 ? "big" :
"little");
	printf("   CHAR_BIT = %i\n", CHAR_BIT);
	printf("   CHAR_MIN = %i\n", CHAR_MIN);
	printf("   CHAR_MAX = %i\n", CHAR_MAX);
	printf("    INT_MIN = %i\n", INT_MIN);
	printf("    INT_MAX = %i\n", INT_MAX);

with both psp-gcc and my gcc and they print exactly the same result:

     sizeof(char) = 1
    sizeof(char*) = 4
    sizeof(void*) = 4
      sizeof(int) = 4
 sizeof(unsigned) = 4
    sizeof(short) = 2
    sizeof(float) = 4
   sizeof(double) = 8
 endianness = little
   CHAR_BIT = 8
   CHAR_MIN = -128
   CHAR_MAX = 127
    INT_MIN = -2147483648
    INT_MAX = 2147483647

This explains why the Pi_Calc program does work when compiled with the
build process I described in my original message. So the difference is
more subtle; maybe a difference in the layout of structs or something.

> Besides that, the
> warning you gave as an example is probably because llvm-gcc 4.2 is a
> newer version of gcc than psp-gcc.

Yup, my psp-gcc is still 4.1.0. And I get these kinds of warnings when
compiling the output of the C backend with psp-gcc:

llvmoutput.c:734: warning: conflicting types for built-in function
'malloc'
llvmoutput.c:1332: warning: return type of 'main' is not 'int'
llvmoutput.c: In function 'loadImage':
llvmoutput.c:2939: warning: pointer targets in passing argument 1 of
'setjmp' differ in signedness
(...)
llvmoutput.c: In function 'png_default_error':
llvmoutput.c:17976: warning: pointer targets in passing argument 1 of
'longjmp' differ in signedness
llvmoutput.c: In function 'png_crc_finish':
llvmoutput.c:18722: warning: 'llvm_cbe_i9_0_reg2mem_1__PHI_TEMPORARY'
may be used uninitialized in this function
(...)

Maybe I should pass "-nostdlib" to llvm-gcc as well. And I'll try
if
using "-O1" instead of "-O5" makes a difference.

Thanks,

Kevin André