[LLVMdev] inttoptr weirdness

Scott Shumaker sshumaker at gmail.com
Mon Dec 14 14:00:06 PST 2009


Never mind, I'm stupid.  I forgot that I was setting the global to
NULL immediately beforehand - so LLVM was optimizing this out.

Scott


On Mon, Dec 14, 2009 at 12:27 PM, Scott Shumaker <sshumaker at gmail.com> wrote:
> 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
>



-- 
---------------------
Scott Shumaker
CTO, magnifeast.com
Online ordering from hundreds of LA delivery and carryout restaurants




More information about the llvm-dev mailing list