<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; ">Thanks for answer, Renato.<div>But I still thing that there is some issue with ARM codegen.</div><div>When I tried running your code you modified I got exactly same LLVM IR result (verified it by comparing output from llvm-dis) - and program on runtime still produces wrong result.</div><div><br></div><div>With some help from another developer we managed to reduce issue to following C code that is simpler:</div><div><br></div><div><font size="1"><span style="font-family: 'courier new', monospace; ">#include <stdio.h></span></font><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">void init(int* value, int val)<span class="Apple-style-span" style="font-size: medium;"> </span></span></font><font size="1"><span style="font-family: 'courier new', monospace; ">{</span></font><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">    *value = val;</span></font><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">    printf("Values: %08x\n", *value);</span></font><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">}</span></font><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">int main() </span></font><font size="1"><span style="font-family: 'courier new', monospace; ">{</span></font><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">    static struct {</span></font><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">        int a;</span></font><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">        int b;</span></font><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">    } value;</span></font><br style="font-family: 'courier new', monospace; "><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">    init(&value.b, 11);</span></font><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">    init(&value.a, 10);</span></font><br style="font-family: 'courier new', monospace; "><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">    printf("%i\n", value.a);</span></font><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">    printf("%i\n", value.b);</span></font></div><font size="1"><span style="font-family: 'courier new', monospace; ">}</span></font><div><font class="Apple-style-span" face="'courier new', monospace"><span class="Apple-style-span" style="font-size: x-small;"><br></span></font></div><div><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-size: medium; ">Correct result would be following output (I am getting this when I'm running ARM+Interpreter, or Windows+JIT):</span><br style="font-family: 'courier new', monospace; "></span><div><font size="1"><span style="font-family: 'courier new', monospace; ">Values: 0000000b</span></font><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">Values: 0000000a</span></font><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">10</span></font><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">11</span></font></div><div><font class="Apple-style-span" face="Helvetica, monospace"><br></font></div><div><font class="Apple-style-span" face="'courier new', monospace"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: Helvetica; font-size: medium; "><font size="1"><span style="font-family: 'courier new', monospace; "><span class="Apple-style-span" style="font-family: Helvetica; font-size: medium; ">But 2.6 LLVM + JIT on ARM, when compiled with llvm-gcc -O3, produces this:</span></span></font></span></span></font></div><div><span class="Apple-style-span" style="font-family: 'courier new', monospace; font-size: x-small; ">Values: 0000000b</span></div><div><font class="Apple-style-span" face="'courier new', monospace"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: Helvetica; font-size: medium; "><font size="1"><span style="font-family: 'courier new', monospace; ">Values: 0000000a</span></font><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">10</span></font><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">10</span></font></span></span></font></div><div><div><div><font class="Apple-style-span" face="Helvetica, monospace"><span class="Apple-style-span" style="font-family: Helvetica; "><div><br></div><div>Here is LLVM IR of main function:</div><div><div><br></div><div><span class="Apple-style-span" style="font-family: 'courier new', monospace; font-size: x-small; ">define i32 @main() nounwind {</span></div></div><div><span class="Apple-style-span" style="font-family: Helvetica; "><font size="1"><span style="font-family: 'courier new', monospace; ">entry:</span></font><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">  store i32 11, i32* getelementptr inbounds (%struct..0._6* @_ZZ4mainE5value, i32 0, i32 1), align 4</span></font><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">  %0 = tail call i32 (i8*, ...)* @printf(i8* noalias getelementptr inbounds ([14 x i8]* @.str, i32 0, i32 0), i32 11) nounwind ; <i32> [#uses=0]</span></font><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">  store i32 10, i32* getelementptr inbounds (%struct..0._6* @_ZZ4mainE5value, i32 0, i32 0), align 8</span></font><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">  %1 = tail call i32 (i8*, ...)* @printf(i8* noalias getelementptr inbounds ([14 x i8]* @.str, i32 0, i32 0), i32 10) nounwind ; <i32> [#uses=0]</span></font><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">  %2 = load i32* getelementptr inbounds (%struct..0._6* @_ZZ4mainE5value, i32 0, i32 0), align 8 ; <i32> [#uses=1]</span></font><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">  %3 = tail call i32 (i8*, ...)* @printf(i8* noalias getelementptr inbounds ([4 x i8]* @.str1, i32 0, i32 0), i32 %2) ; <i32> [#uses=0]</span></font><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">  %4 = load i32* getelementptr inbounds (%struct..0._6* @_ZZ4mainE5value, i32 0, i32 1), align 4 ; <i32> [#uses=1]</span></font><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">  %5 = tail call i32 (i8*, ...)* @printf(i8* noalias getelementptr inbounds ([4 x i8]* @.str1, i32 0, i32 0), i32 %4) ; <i32> [#uses=0]</span></font><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">  ret i32 0</span></font><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">}</span></font></span></div><div><font class="Apple-style-span" face="'courier new', monospace"><span class="Apple-style-span" style="font-size: x-small;"><br></span></font></div><div><span class="Apple-style-span" style="font-family: Helvetica; ">It looks like the JIT compiler doesn't handle the following bitcode instructions correctly:<br><font size="1"><span style="font-family: 'courier new', monospace; ">  store i32 11, i32* getelementptr inbounds (%struct..0._6* @_ZZ4mainE5value, i32 0, i32 1), align 4</span></font><br>and<br><font size="1"><span style="font-family: 'courier new', monospace; ">  %4 = load i32* getelementptr inbounds (%struct..0._6* @_ZZ4mainE5value, i32 0, i32 1), align 4 ; <i32> [#uses=1]</span></font><br>It ignores the "i32 1" offset in the getelementptr bitcode instruction.</span></div><div><br></div><div>Here is produced ARM assembly of main function displayed from GDB:</div><div><span class="Apple-style-span" style="font-family: Helvetica; "><br><div style="margin-left: 40px; "><font size="1"><span style="font-family: 'courier new', monospace; ">(gdb) x/30i FPtr</span></font><br></div><div style="margin-left: 40px; "><font size="1"><span style="font-family: 'courier new', monospace; ">0x40029010:    sub    sp, sp, #16    ; 0x10</span></font><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">0x40029014:    str    lr, [sp, #12]</span></font><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">0x40029018:    str    r11, [sp, #8]</span></font><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">0x4002901c:    str    r5, [sp, #4]</span></font><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">0x40029020:    str    r4, [sp]</span></font><br><br></div>Allocate four entries on the stack, and save the return address, r11, r5, and r4.<br><div style="margin-left: 40px; "><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">0x40029024:    ldr    r4, [pc, #88]    ; 0x40029084</span></font><br><br></div>Address of the value variable in r4.<br><div style="margin-left: 40px; "><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">0x40029028:    mov    r1, #11    ; 0xb</span></font><br><font size="1"><span style="font-family: 'courier new', monospace; ">0x4002902c:    str    r1, [r4]</span></font><br><font size="1"><span style="font-family: 'courier new', monospace; ">0x40029030:    ldr    r5, [pc, #80]    ; 0x40029088</span></font><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">0x40029034:    mov    r0, r5</span></font><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">0x40029038:    bl    0x40009008</span></font><br><br></div>Inline the init function: store 11 at the address of the "value" variable, call printf with the string from r5. This is a bug, should have stored at an offset of four (str r1, [r4,4]).<br><div style="margin-left: 40px; "><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">0x4002903c:    mov    r1, #10    ; 0xa</span></font><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">0x40029040:    str    r1, [r4]</span></font><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">0x40029044:    mov    r0, r5</span></font><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">0x40029048:    bl    0x40009008<br><br></span></font></div>Inline the init function: store 10 at the address of the "value" variable, call printf with the string from r5. This looks OK.<font size="1"><span style="font-family: 'courier new', monospace; "></span></font><br><font size="1"><span style="font-family: 'courier new', monospace; "></span></font><div style="margin-left: 40px; "><font size="1"><span style="font-family: 'courier new', monospace; "><br style="font-family: 'courier new', monospace; "></span></font><font size="1"><span style="font-family: 'courier new', monospace; ">0x4002904c:    ldr    r1, [r4]</span></font><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">0x40029050:    ldr    r5, [pc, #52]    ; 0x4002908c</span></font><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">0x40029054:    mov    r0, r5</span></font><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">0x40029058:    bl    0x40009008</span></font><br><br></div>Load first number from the structure and print its value.<br><div style="margin-left: 40px; "><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">0x4002905c:    ldr    r1, [r4]</span></font><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">0x40029060:    mov    r0, r5</span></font><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">0x40029064:    bl    0x40009008</span></font><br><br></div>Load first number from the structure and print its value. This is bug also, should have been "ldr r1, [r4,4]".<br><div style="margin-left: 40px; "><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">0x40029068:    mov    r0, #0    ; 0x0</span></font><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">0x4002906c:    ldr    r4, [sp]</span></font><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">0x40029070:    ldr    r5, [sp, #4]</span></font><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">0x40029074:    ldr    r11, [sp, #8]</span></font><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">0x40029078:    ldr    lr, [sp, #12]</span></font><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">0x4002907c:    add    sp, sp, #16    ; 0x10</span></font><br style="font-family: 'courier new', monospace; "><font size="1"><span style="font-family: 'courier new', monospace; ">0x40029080:    bx    lr</span></font><br style="font-family: 'courier new', monospace; "></div><br>And at the end restore registers from the stack and return. </span></div><div><br></div><div>Can somebody confirm that this is a bug? Or am I missing something else here?</div><div><br></div><div>--</div><div>Martins Mozeiko</div><div><br></div></span></font></div><div><br></div><div>On Feb 17, 2010, at 12:23 , Renato Golin wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div>On 15 February 2010 14:49, Martins Mozeiko <<a href="mailto:49640f8a@gmail.com">49640f8a@gmail.com</a>> wrote:<br><blockquote type="cite">#include <stdio.h><br></blockquote><blockquote type="cite">struct Global {<br></blockquote><blockquote type="cite"> typedef unsigned char ArrayType[4];<br></blockquote><blockquote type="cite"> ArrayType value;<br></blockquote><blockquote type="cite"> Global(const ArrayType& arg) {<br></blockquote><blockquote type="cite">   for (int i = 0; i < 4; i++) this->value[i] = arg[i];<br></blockquote><blockquote type="cite"> }<br></blockquote><blockquote type="cite">};<br></blockquote><blockquote type="cite">static const unsigned char arr[] = { 1, 2, 3, 4 };<br></blockquote><blockquote type="cite">static const Global Constant(arr);<br></blockquote><blockquote type="cite">int main() {<br></blockquote><blockquote type="cite"> for (int i=0; i<4; i++) printf("%i", Constant.value[i]);<br></blockquote><blockquote type="cite">}<br></blockquote><br>Compiling with clang I got lots of errors, but boils down to two problems:<br><br><blockquote type="cite"> typedef unsigned char ArrayType[4];<br></blockquote><br>const_array.cpp:3:2: error: type name does not allow storage class to<br>be specified<br> typedef unsigned char ArrayType[4];<br> ^<br><br>Which, as far as I can tell, it's confusing ArrayType[4] by a<br>declaration of an unsigned char[4] type.<br><br>I've changed your code slightly to make it compile with clang, but I<br>haven't been able to make it print 4444, not even with your own code,<br>not even at -O3. There seems to be nothing wrong with the LLVM IR<br>generated by your code, too, even at -O3.<br><br>#include <stdio.h><br>typedef unsigned char ArrayType;<br>struct Global {<br> ArrayType value[4];<br> Global(const ArrayType* arg) {<br>   for (int i = 0; i < 4; i++) this->value[i] = arg[i];<br> }<br>};<br>static const unsigned char arr[] = { 1, 2, 3, 4 };<br>static const struct Global Constant(arr);<br>int main() {<br> for (int i=0; i<4; i++) printf("%i", Constant.value[i]);<br>}<br><br>See if that helps. I think it has nothing to do with code generation, though.<br><br>cheers,<br>--renato<br><br><a href="http://systemcall.org/">http://systemcall.org/</a><br><br>Reclaim your digital rights, eliminate DRM, learn more at<br>http://www.defectivebydesign.org/what_is_drm<br></div></blockquote></div><br></div></div></body></html>