<div dir="ltr"><div>Since the getelementptrs were implicitly generated by the CreateStore/Load I'm not sure how to get access to them.<br><br>So I hacked the assignment to be done thrice: once using a manual decomposition into two GEPs and stores, once using the "big" CreateStore, once via the setGlobal function, printing addresses and memory contents at each point to the degree that I have access to them.</div><div><br>It seems the following GEPs compute the same address?! I can buy myself not understanding how GEP works and doing it wrong, but builder.CreateStore() creates what look like identical GEPs implicitly...<br></div><div><br><span style="font-family:monospace,monospace;font-size:x-small">i8** getelementptr inbounds ({ i8*, i32 }, { i8*, i32 }* @foo, i32 0, i32 0), align 4<br></span><span style="font-family:monospace,monospace;font-size:x-small">i32* getelementptr inbounds ({ i8*, i32 }, { i8*, i32 }* @foo, i32 0, i32 1), align 4<br></span><br>The details.<br><br>This is the relevant part from my codegen:</div><div><br></div><div><div><div><font face="monospace, monospace" size="1">            auto ty = val->getType();</font></div><div><font face="monospace, monospace" size="1">            cout << "val type:" << endl;</font></div><div><font face="monospace, monospace" size="1">            ty->dump();</font></div><div><font face="monospace, monospace" size="1">            cout << "ptr type:" << endl;</font></div><div><font face="monospace, monospace" size="1">            ptr->getType()->dump();</font></div><div><font face="monospace, monospace" size="1">            // Print memory</font></div><div><font face="monospace, monospace" size="1">            ctx.EmitCall1("debugPointer", ptr);</font></div><div><font face="monospace, monospace" size="1">            // Set class pointer</font></div><div><font face="monospace, monospace" size="1">            auto c = ctx.bld.CreateExtractValue(val, 0, "class");</font></div><div><font face="monospace, monospace" size="1">            auto cp = ctx.bld.CreateConstGEP2_32(ty, ptr, 0, 0);</font></div><div><font face="monospace, monospace" size="1">            auto cx = ctx.bld.CreatePtrToInt(cp, ctx.Int32Type());</font></div><div><font face="monospace, monospace" size="1">            ctx.EmitCall1("debugInt", cx);</font></div><div><font face="monospace, monospace" size="1">            ctx.bld.CreateStore(c, cp);</font></div><div><font face="monospace, monospace" size="1">            // Set datum</font></div><div><font face="monospace, monospace" size="1">            auto d = ctx.bld.CreateExtractValue(val, 1, "datum");</font></div><div><font face="monospace, monospace" size="1">            auto dp = ctx.bld.CreateConstGEP2_32(ty, ptr, 0, 1);</font></div><div><font face="monospace, monospace" size="1">            auto dx = ctx.bld.CreatePtrToInt(dp, ctx.Int32Type());</font></div><div><font face="monospace, monospace" size="1">            ctx.EmitCall1("debugInt", dx);</font></div><div><font face="monospace, monospace" size="1">            ctx.bld.CreateStore(d, dp);</font></div><div><font face="monospace, monospace" size="1">            // Print memory</font></div><div><font face="monospace, monospace" size="1">            ctx.EmitCall1("debugPointer", ptr);</font></div><div><font face="monospace, monospace" size="1">            // Do the same with a single store</font></div><div><font face="monospace, monospace" size="1">            ctx.bld.CreateStore(val, ptr);</font></div><div><font face="monospace, monospace" size="1">            // Print memory</font></div><div><font face="monospace, monospace" size="1">            ctx.EmitCall1("debugPointer", ptr);</font></div><div><font face="monospace, monospace" size="1">            // Call out</font></div><div><font face="monospace, monospace" size="1">            ctx.EmitCall2("setGlobal", ptr, val);</font></div><div><font face="monospace, monospace" size="1">            // Print memory</font></div><div><font face="monospace, monospace" size="1">            ctx.EmitCall1("debugPointer", ptr);</font></div></div></div><div><br></div><div>Here is the compile-time output showing types of the value and the pointer:<br><br><div><div><font face="monospace, monospace" size="1">val type:</font></div><div><font face="monospace, monospace" size="1">{ i8*, i32 }</font></div><div><font face="monospace, monospace" size="1">ptr type:</font></div><div><font face="monospace, monospace" size="1">{ i8*, i32 }*</font></div></div><div><br></div><div><font face="arial, helvetica, sans-serif">Here is the IR dump for the function (after a couple of passes), right before it's fed to the JIT:</font></div><div><br></div><div><font face="monospace, monospace" size="1">define { i8*, i32 } @"__anonToplevel/0"() prefix { i8*, i32 } (i32)* @"XEP:__anonToplevel/0" {</font></div><div><font face="monospace, monospace" size="1">entry:</font></div><div><font face="monospace, monospace" size="1">  %0 = call { i8*, i32 } @debugPointer({ i8*, i32 }* nonnull @foo)</font></div><div><font face="monospace, monospace" size="1">  %1 = call { i8*, i32 } @debugInt(i32 ptrtoint ({ i8*, i32 }* @foo to i32))</font></div><div><font face="monospace, monospace" size="1">  store i8* @FixnumClass, i8** getelementptr inbounds ({ i8*, i32 }, { i8*, i32 }* @foo, i32 0, i32 0), align 4</font></div><div><font face="monospace, monospace" size="1">  %2 = call { i8*, i32 } @debugInt(i32 ptrtoint (i32* getelementptr inbounds ({ i8*, i32 }, { i8*, i32 }* @foo, i32 0, i32 1) to i32))</font></div><div><font face="monospace, monospace" size="1">  store i32 123, i32* getelementptr inbounds ({ i8*, i32 }, { i8*, i32 }* @foo, i32 0, i32 1), align 4</font></div><div><font face="monospace, monospace" size="1">  %3 = call { i8*, i32 } @debugPointer({ i8*, i32 }* nonnull @foo)</font></div><div><font face="monospace, monospace" size="1">  store i8* @FixnumClass, i8** getelementptr inbounds ({ i8*, i32 }, { i8*, i32 }* @foo, i32 0, i32 0), align 4</font></div><div><font face="monospace, monospace" size="1">  store i32 123, i32* getelementptr inbounds ({ i8*, i32 }, { i8*, i32 }* @foo, i32 0, i32 1), align 4</font></div><div><font face="monospace, monospace" size="1">  %4 = call { i8*, i32 } @debugPointer({ i8*, i32 }* nonnull @foo)</font></div><div><font face="monospace, monospace" size="1">  call void @setGlobal({ i8*, i32 }* nonnull @foo, { i8*, i32 } { i8* @FixnumClass, i32 123 })</font></div><div><font face="monospace, monospace" size="1">  %5 = call { i8*, i32 } @debugPointer({ i8*, i32 }* nonnull @foo)</font></div><div><font face="monospace, monospace" size="1">  ret { i8*, i32 } { i8* @FixnumClass, i32 123 }</font></div><div><font face="monospace, monospace" size="1">}</font></div><div><br></div><div>​Here is the runtime from calling the JITed function, including memory addresses and contents, with my annotations:<br></div></div><div><br></div><div><font face="monospace, monospace" size="1"># Before</font></div><div><div><div><font face="monospace, monospace" size="1">p = 03C10000</font></div><div><font face="monospace, monospace" size="1">  class: 00000000</font></div><div><font face="monospace, monospace" size="1">  datum: 00000000</font></div><div><font face="monospace, monospace" size="1"># Should be address of the class slot --> correct</font></div><div><font face="monospace, monospace" size="1">x = 03C10000</font></div><div><font face="monospace, monospace" size="1"># Should be address of the datum slot, ie address of class slot + 4 --> incorrect</font></div><div><font face="monospace, monospace" size="1">x = 03C10000</font></div><div><font face="monospace, monospace" size="1"># Yeah, both values want to class slot, so actual class pointer got clobbered</font></div><div><font face="monospace, monospace" size="1">p = 03C10000</font></div><div><font face="monospace, monospace" size="1">  class: 0000007B</font></div><div><font face="monospace, monospace" size="1">  datum: 00000000</font></div><div><font face="monospace, monospace" size="1"># Same result from the single CreateStore</font></div><div><font face="monospace, monospace" size="1">p = 03C10000</font></div><div><font face="monospace, monospace" size="1">  class: 0000007B</font></div><div><font face="monospace, monospace" size="1">  datum: 00000000</font></div><div><font face="monospace, monospace" size="1"># Calling out to setGlobal as in my first email works</font></div><div><font face="monospace, monospace" size="1">p = 03C10000</font></div><div><font face="monospace, monospace" size="1">  class: 039D2E98</font></div><div><font face="monospace, monospace" size="1">  datum: 0000007B</font></div></div></div><div><br></div><div>Finally, I didn't manage nice disassembly yet, so here is the last output from --print-after-all for the function. The bizarre thing is that even this looks correct: the debugInt is called first with @foo, then @foo+4, and the stores seem to be going to the right addresses as well: @foo and @foo+4!</div><div><div><br></div><div><font face="monospace, monospace" size="1">BB#0: derived from LLVM BB %entry</font></div><div><font face="monospace, monospace" size="1">        PUSHi32 <ga:@foo>, %ESP<imp-def>, %ESP<imp-use></font></div><div><font face="monospace, monospace" size="1">        CFI_INSTRUCTION <call frame instruction></font></div><div><font face="monospace, monospace" size="1">        CALLpcrel32 <ga:@debugPointer>, <regmask %BH %BL %BP %BPL %BX %DI %DIL %EBP %EBX %EDI %ESI %SI %SIL>, %ESP<imp-use>, %ESP<imp-def>, %EAX<imp-def,dead>, %EDX<imp-def,dead></font></div><div><font face="monospace, monospace" size="1">        %ESP<def,tied1> = ADD32ri8 %ESP<tied0>, 4, %EFLAGS<imp-def,dead></font></div><div><font face="monospace, monospace" size="1">        CFI_INSTRUCTION <call frame instruction></font></div><div><font face="monospace, monospace" size="1">        PUSHi32 <ga:@foo>, %ESP<imp-def>, %ESP<imp-use></font></div><div><font face="monospace, monospace" size="1">        CFI_INSTRUCTION <call frame instruction></font></div><div><font face="monospace, monospace" size="1">        CALLpcrel32 <ga:@debugInt>, <regmask %BH %BL %BP %BPL %BX %DI %DIL %EBP %EBX %EDI %ESI %SI %SIL>, %ESP<imp-use>, %ESP<imp-def>, %EAX<imp-def,dead>, %EDX<imp-def,dead></font></div><div><font face="monospace, monospace" size="1">        %ESP<def,tied1> = ADD32ri8 %ESP<tied0>, 4, %EFLAGS<imp-def,dead></font></div><div><font face="monospace, monospace" size="1">        CFI_INSTRUCTION <call frame instruction></font></div><div><font face="monospace, monospace" size="1">        MOV32mi %noreg, 1, %noreg, <ga:@foo>, %noreg, <ga:@JazzFixnumClass>; mem:ST4[getelementptr inbounds ({ i8*, i32 }, { i8*, i32 }* @foo, i32 0, i32 0)]</font></div><div><font face="monospace, monospace" size="1">        PUSHi32 <ga:@foo+4>, %ESP<imp-def>, %ESP<imp-use></font></div><div><font face="monospace, monospace" size="1">        CFI_INSTRUCTION <call frame instruction></font></div><div><font face="monospace, monospace" size="1">        CALLpcrel32 <ga:@debugInt>, <regmask %BH %BL %BP %BPL %BX %DI %DIL %EBP %EBX %EDI %ESI %SI %SIL>, %ESP<imp-use>, %ESP<imp-def>, %EAX<imp-def,dead>, %EDX<imp-def,dead></font></div><div><font face="monospace, monospace" size="1">        %ESP<def,tied1> = ADD32ri8 %ESP<tied0>, 4, %EFLAGS<imp-def,dead></font></div><div><font face="monospace, monospace" size="1">        CFI_INSTRUCTION <call frame instruction></font></div><div><font face="monospace, monospace" size="1">        MOV32mi %noreg, 1, %noreg, <ga:@foo+4>, %noreg, 123; mem:ST4[getelementptr inbounds ({ i8*, i32 }, { i8*, i32 }* @foo, i32 0, i32 1)]</font></div><div><font face="monospace, monospace" size="1">        PUSHi32 <ga:@foo>, %ESP<imp-def>, %ESP<imp-use></font></div><div><font face="monospace, monospace" size="1">        CFI_INSTRUCTION <call frame instruction></font></div><div><font face="monospace, monospace" size="1">        CALLpcrel32 <ga:@debugPointer>, <regmask %BH %BL %BP %BPL %BX %DI %DIL %EBP %EBX %EDI %ESI %SI %SIL>, %ESP<imp-use>, %ESP<imp-def>, %EAX<imp-def,dead>, %EDX<imp-def,dead></font></div><div><font face="monospace, monospace" size="1">        %ESP<def,tied1> = ADD32ri8 %ESP<tied0>, 4, %EFLAGS<imp-def,dead></font></div><div><font face="monospace, monospace" size="1">        CFI_INSTRUCTION <call frame instruction></font></div><div><font face="monospace, monospace" size="1">        MOV32mi %noreg, 1, %noreg, <ga:@foo>, %noreg, <ga:@JazzFixnumClass>; mem:ST4[getelementptr inbounds ({ i8*, i32 }, { i8*, i32 }* @foo, i32 0, i32 0)]</font></div><div><font face="monospace, monospace" size="1">        MOV32mi %noreg, 1, %noreg, <ga:@foo+4>, %noreg, 123; mem:ST4[getelementptr inbounds ({ i8*, i32 }, { i8*, i32 }* @foo, i32 0, i32 1)]</font></div><div><font face="monospace, monospace" size="1">        PUSHi32 <ga:@foo>, %ESP<imp-def>, %ESP<imp-use></font></div><div><font face="monospace, monospace" size="1">        CFI_INSTRUCTION <call frame instruction></font></div><div><font face="monospace, monospace" size="1">        CALLpcrel32 <ga:@debugPointer>, <regmask %BH %BL %BP %BPL %BX %DI %DIL %EBP %EBX %EDI %ESI %SI %SIL>, %ESP<imp-use>, %ESP<imp-def>, %EAX<imp-def,dead>, %EDX<imp-def,dead></font></div><div><font face="monospace, monospace" size="1">        %ESP<def,tied1> = ADD32ri8 %ESP<tied0>, 4, %EFLAGS<imp-def,dead></font></div><div><font face="monospace, monospace" size="1">        CFI_INSTRUCTION <call frame instruction></font></div><div><font face="monospace, monospace" size="1">        PUSH32i8 123, %ESP<imp-def>, %ESP<imp-use></font></div><div><font face="monospace, monospace" size="1">        CFI_INSTRUCTION <call frame instruction></font></div><div><font face="monospace, monospace" size="1">        PUSHi32 <ga:@JazzFixnumClass>, %ESP<imp-def>, %ESP<imp-use></font></div><div><font face="monospace, monospace" size="1">        CFI_INSTRUCTION <call frame instruction></font></div><div><font face="monospace, monospace" size="1">        PUSHi32 <ga:@foo>, %ESP<imp-def>, %ESP<imp-use></font></div><div><font face="monospace, monospace" size="1">        CFI_INSTRUCTION <call frame instruction></font></div><div><font face="monospace, monospace" size="1">        CALLpcrel32 <ga:@setGlobal>, <regmask %BH %BL %BP %BPL %BX %DI %DIL %EBP %EBX %EDI %ESI %SI %SIL>, %ESP<imp-use>, %ESP<imp-def></font></div><div><font face="monospace, monospace" size="1">        %ESP<def,tied1> = ADD32ri8 %ESP<tied0>, 12, %EFLAGS<imp-def,dead></font></div><div><font face="monospace, monospace" size="1">        CFI_INSTRUCTION <call frame instruction></font></div><div><font face="monospace, monospace" size="1">        PUSHi32 <ga:@foo>, %ESP<imp-def>, %ESP<imp-use></font></div><div><font face="monospace, monospace" size="1">        CFI_INSTRUCTION <call frame instruction></font></div><div><font face="monospace, monospace" size="1">        CALLpcrel32 <ga:@debugPointer>, <regmask %BH %BL %BP %BPL %BX %DI %DIL %EBP %EBX %EDI %ESI %SI %SIL>, %ESP<imp-use>, %ESP<imp-def>, %EAX<imp-def,dead>, %EDX<imp-def,dead></font></div><div><font face="monospace, monospace" size="1">        %ESP<def,tied1> = ADD32ri8 %ESP<tied0>, 4, %EFLAGS<imp-def,dead></font></div><div><font face="monospace, monospace" size="1">        CFI_INSTRUCTION <call frame instruction></font></div><div><font face="monospace, monospace" size="1">        %EAX<def> = MOV32ri <ga:@JazzFixnumClass></font></div><div><font face="monospace, monospace" size="1">        %EDX<def> = MOV32ri 123</font></div><div><font face="monospace, monospace" size="1">        RETL %EAX<kill>, %EDX<kill></font></div></div><div><br></div><div>Also, I have essentially identical code working perfectly fine when the memory being written to is from @alloca.<br><br>I am completely clueless. Any suggestions most welcome.</div><div><br></div><div>Cheers,</div><div><br></div><div> -- nikodemus</div><div><br></div></div>