[llvm-dev] Some strange i64 behavior with arm 32bit. (Raspberry Pi)
Moritz Angermann via llvm-dev
llvm-dev at lists.llvm.org
Sat Dec 2 23:26:00 PST 2017
Alright, so after some more debugging (injeting print statements at the llvm ir level),
I came across the following:
GHC has the following code for the C into STG and back bridge: `RunStg`, which is defined
in https://github.com/ghc/ghc/blob/master/rts/StgCRun.c; the resulting llvm ir ends up being:
```
; Function Attrs: nounwind
define hidden %struct.StgRegTable* @StgRun(i8* ()* ()*, %struct.StgRegTable*) local_unnamed_addr #0 {
%3 = tail call %struct.StgRegTable* asm sideeffect "stmfd sp!, {r4-r11, ip, lr}\0A\09vstmdb sp!, {d8-d11}\0A\09sub sp, sp, $3\0A\09mov r4, $2\0A\09bx $1\0A\09.globl StgReturn\0A\09.type StgReturn, %function\0AStgReturn:\0A\09add sp, sp, $3\0A\09mov $0, r7\0A\09vldmia sp!, {d8-d11}\0A\09ldmfd sp!, {r4-r11, ip, lr}\0A\09", "=r,r,r,i,~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r12},~{lr}"(i8* ()* ()* %0, %struct.StgRegTable* %1, i32 8192) #1, !srcloc !3
ret %struct.StgRegTable* %3
}
```
The assembly for better readability reads:
stmfd sp!, {r4-r11, ip, lr}
vstmdb sp!, {d8-d11}
sub sp, sp, $3
mov r4, $2
bx $1
.globl StgReturn
.type StgReturn, %function
StgReturn:
add sp, sp, $3
mov $0, r7
vldmia sp!, {d8-d11}
ldmfd sp!, {r4-r11, ip, lr}
And when this results in the following assembly being emitted (for armv-unknown-linux-gnueabihf):
```
00000074 <StgRun>:
74: e92d4ff0 push {r4, r5, r6, r7, r8, r9, sl, fp, lr}
78: e28db01c add fp, sp, #28, 0
7c: e92d5ff0 push {r4, r5, r6, r7, r8, r9, sl, fp, ip, lr}
80: ed2d8b08 vpush {d8-d11}
84: e24dda02 sub sp, sp, #8192 ; 0x2000
88: e1a04001 mov r4, r1
8c: e12fff10 bx r0
00000090 <StgReturn>:
90: e28dda02 add sp, sp, #8192 ; 0x2000
94: e1a00007 mov r0, r7
98: ecbd8b08 vpop {d8-d11}
9c: e8bd5ff0 pop {r4, r5, r6, r7, r8, r9, sl, fp, ip, lr}
a0: e8bd8ff0 pop {r4, r5, r6, r7, r8, r9, sl, fp, pc}
```
By adding extra ptinf statements, I found out that adding a `printf` statement after the assembly and before
the `ret`, the generated code looks slightly different:
```
00000074 <StgRun>:
74: e92d4ff0 push {r4, r5, r6, r7, r8, r9, sl, fp, lr}
78: e28db01c add fp, sp, #28, 0
7c: e24dd004 sub sp, sp, #4, 0
80: e92d5ff0 push {r4, r5, r6, r7, r8, r9, sl, fp, ip, lr}
84: ed2d8b08 vpush {d8-d11}
88: e24dda02 sub sp, sp, #8192 ; 0x2000
8c: e1a04001 mov r4, r1
90: e12fff10 bx r0
00000094 <StgReturn>:
94: e28dda02 add sp, sp, #8192 ; 0x2000
98: e1a00007 mov r0, r7
9c: ecbd8b08 vpop {d8-d11}
a0: e8bd5ff0 pop {r4, r5, r6, r7, r8, r9, sl, fp, ip, lr}
a4: e58d0000 str r0, [sp]
a8: e3a00002 mov r0, #2, 0
ac: ebfffffe bl 44 <.LdebugEnd>
b0: e59d0000 ldr r0, [sp]
b4: e24bd01c sub sp, fp, #28, 0
b8: e8bd8ff0 pop {r4, r5, r6, r7, r8, r9, sl, fp, pc}
```
and we can see that an additional `sp = sp - 4` was added.
With the log statement in StgRun, subsequent log statements so far work.
Now I wonder
a) could I write this logic in llvm ir directly,
without having to resort to assembly?
b) could I force llvm to emit 32 instead of 28 somehow? to make sure
my sp is 8byte aligned?
Of course I'm happy to take any other ideas as well.
Cheers,
Moritz
> On Dec 1, 2017, at 6:30 PM, Moritz Angermann <moritz.angermann at gmail.com> wrote:
>
> Hi Tim,
> thanks for the swift response!
>
> @debug is defined in the same module, which makes this all the more confusing.
>
>
> The target information from the working example are:
> target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
> target triple = "armv6kz--linux-gnueabihf"
>
>
> from the ghc produced module:
> target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
> target triple = "arm-unknown-linux-gnueabihf"
>
> However there ones more thing, I could think of, arm does allow mixed mode
> I believe. And as such as the code from the ghc produced module is called
> from outside of the module, could the endianness be set there prior to
> entering the function?
>
> The working module contains the main directly and is not called from a main
> function in a different module.
>
> I've also tried to define a regular c function with the same code and called
> that from within the ghccc function with the same (incorrect) results.
>
> Any further ideas I could expore?
>
>
> Cheers,
> Moritz
>
>> On Dec 1, 2017, at 4:26 PM, Tim Northover <t.p.northover at gmail.com> wrote:
>>
>> Hi Moritz,
>>> If someone could offer some hint, where to look further for debugging this, I'd very much appreciate the advice!
>>> I'm a bit lost right now how to figure out why I end up getting swapped words.
>>
>> If one file was compiled for big-endian ARM and the other for
>> little-endian that could be the result. I'm not aware of any other
>> possible cause and from local tests I don't think the "ghccc" alone
>> explains the difference.
>>
>> So maybe some glitch in how GHC was configured on your system? What's
>> the triple at the top of the GHC module and the module containing the
>> definition of @debug?
>>
>> Cheers.
>>
>> Tim.
>
More information about the llvm-dev
mailing list