[LLVMdev] inttoptr weirdness

Scott Shumaker sshumaker at gmail.com
Mon Dec 14 12:27:33 PST 2009


Hi again.

I have a complex type system in my custom language that isn't easily
representable as LLVM IR types, so I figured I could mostly get along
with treating my types as i8* and doing the appropriate bitcasts and
inttoptr instructions, and doing pointer arithmetic myself (by casting
the pointers to ints, adding the appropriate byte offsets, and then
casting back to pointers).

However, I've found some oddities.  While I have no problems
generating IR, when I run it through the optimizer (opt -O3), it
generates what appears to be totally wrong code.

Here's my test case:

I have a global called *testObj*.  It would look like this in C:

struct TestObjClass
{
  int32 dummy1, dummy2;
  int32* m_array;
}

extern TestObjClass* testObj;

and I'm trying to access:

testObj->m_array[1] = 10

Theoretically, this should be a load to get the pointer to testObj
(since it's a global), I should add 8 bytes, then do another load (to
load the address of the array), add 4 bytes to get the array[1]
element, and then store at that pointer the number 10.

Here's my original output:

@"compile-test::*testObj*" = external constant i8*		; <i8**> [#uses=1]

define void @"compile-test::__toplevel-main"() {
entry:
	store i8* null, i8** @"compile-test::*testObj*"
	%1 = load i8** @"compile-test::*testObj*"		; <i8*> [#uses=1]
	%2 = ptrtoint i8* %1 to i32		; <i32> [#uses=1]
	%3 = add i32 %2, 8		; <i32> [#uses=1]
	%4 = inttoptr i32 %3 to i8*		; <i8*> [#uses=1]
	%5 = load i8* %4		; <i8> [#uses=1]
	%6 = inttoptr i8 %5 to i8*		; <i8*> [#uses=1]
	%7 = ptrtoint i8* %6 to i32		; <i32> [#uses=1]
	%8 = add i32 %7, 4		; <i32> [#uses=1]
	%9 = inttoptr i32 %8 to i8*		; <i8*> [#uses=1]
	%10 = bitcast i8* %9 to i32*		; <i32*> [#uses=1]
	store i32 10, i32* %10
	ret void
}

This seems right to me.  However, when I run it through opt -O3 and
the through llvm-dis:

@"compile-test::*testObj*" = external constant i8*		; <i8**> [#uses=1]
define void @"compile-test::__toplevel-main"() {
entry:
	%0 = load i8* inttoptr (i64 8 to i8*), align 8		; <i8> [#uses=1]
	%1 = inttoptr i8 %0 to i8*		; <i8*> [#uses=1]
	%2 = ptrtoint i8* %1 to i32		; <i32> [#uses=1]
	%3 = add i32 %2, 4		; <i32> [#uses=1]
	%4 = inttoptr i32 %3 to i32*		; <i32*> [#uses=1]
	store i32 10, i32* %4
	ret void
}

Notice how there's no mention of compile-test::*testObj* at all.
Instead, the first line is loading from (i64 8)!  What am I doing
wrong?

Thanks in advance,
Scott



More information about the llvm-dev mailing list