[Caml-list] arm backend

20 views
Skip to first unread message

Joel Reymont

unread,
Apr 30, 2009, 8:14:52 AM4/30/09
to O'Caml Mailing List
Is the ARM backend (ocamlopt) usable and actively maintained?

Thanks, Joel

---
Mac hacker with a performance bent
http://linkedin.com/in/joelreymont

_______________________________________________
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
Archives: http://caml.inria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs

Sylvain Le Gall

unread,
Apr 30, 2009, 9:28:38 AM4/30/09
to caml...@inria.fr
Hello,

On 30-04-2009, Joel Reymont <joe...@gmail.com> wrote:
> Is the ARM backend (ocamlopt) usable and actively maintained?
>

Xavier talked a little about it on 2009 OCaml Meeting. It seems that he
is interested in maintaining it but there is problem with floating point
computation (depending on some modes you can have hard/soft/semi-soft...
floating point computation). I don't know the status and Xavier Leroy
will explain you better the issue.

AFAIK, he is interested in making ocamlopt backend work on NSLU2...

Regards
Sylvain Le Gall

Stéphane Glondu

unread,
Apr 30, 2009, 2:01:12 PM4/30/09
to Sylvain Le Gall, caml...@inria.fr
Sylvain Le Gall a écrit :

> Xavier talked a little about it on 2009 OCaml Meeting. It seems that he
> is interested in maintaining it but there is problem with floating point
> computation (depending on some modes you can have hard/soft/semi-soft...
> floating point computation). I don't know the status and Xavier Leroy
> will explain you better the issue.

http://caml.inria.fr/mantis/view.php?id=3746


Cheers,

--
Stéphane

Nathaniel Gray

unread,
Apr 30, 2009, 3:19:34 PM4/30/09
to caml...@inria.fr
On Thu, Apr 30, 2009 at 11:03 AM, Stéphane Glondu <st...@glondu.net> wrote:
>
> http://caml.inria.fr/mantis/view.php?id=3746

Speaking of which, has anybody built an ocaml cross compiler for the
iphone that can work with native cocoa touch apps built with the
official SDK? It's probably too late for my current project but in
the future I'd love to use ocaml for my iPhone projects. I tried
following the instructions here[1] with some necessary
modifications[2] to get the assembler to work but my test app crashed
as soon as it entered ocaml code. I don't know enough about the ARM
platform to say why.

Cheers,
-n8

[1] http://web.yl.is.s.u-tokyo.ac.jp/~tosh/ocaml-on-iphone/
[2] I had to change all '.global' to '.globl' in arm.s and
arm/emit.mlp. I have no idea what that signifies.

--
Nathan Gray
http://www.n8gray.org/

Mattias Engdegård

unread,
May 1, 2009, 8:02:47 AM5/1/09
to n8g...@gmail.com, caml...@inria.fr
>[2] I had to change all '.global' to '.globl' in arm.s and
>arm/emit.mlp. I have no idea what that signifies.

Only that Apple's assembler only understands .globl. Gas (the assembler
in GNU binutils) should accept both .global and .globl, so it is probably
safe to use the latter only. There is no difference in semantics.

Another pseudo-op that sometimes causes problems is .align whose exact
behaviour with respect to its argument varies between platforms.
Both gas and Apple's as accept .p2align, so this is usually a safer
choice.

Nathaniel Gray

unread,
May 1, 2009, 2:27:23 PM5/1/09
to Mattias Engdegård, caml...@inria.fr
On Fri, May 1, 2009 at 5:02 AM, Mattias Engdegård <mat...@virtutech.se> wrote:
>>[2] I had to change all '.global' to '.globl' in arm.s and
>>arm/emit.mlp.  I have no idea what that signifies.
>
> Only that Apple's assembler only understands .globl. Gas (the assembler
> in GNU binutils) should accept both .global and .globl, so it is probably
> safe to use the latter only. There is no difference in semantics.

Ah, mystery solved. Thanks!

> Another pseudo-op that sometimes causes problems is .align whose exact
> behaviour with respect to its argument varies between platforms.
> Both gas and Apple's as accept .p2align, so this is usually a safer
> choice.

It's all very confusing to me because I thought Apple's assembler
*was* gas. In the man page for as it's described as "Mac OS X Mach-O
GNU-based assemblers". The -v flag for the iPhone version of as
gives:

"Apple Computer, Inc. version cctools-667.10.0~186, GNU assembler version 1.38"

Very odd that they decided to take out support for .global in their version...

Cheers,
-n8

_______________________________________________

Mattias Engdegård

unread,
May 1, 2009, 3:24:32 PM5/1/09
to n8g...@gmail.com, caml...@inria.fr
>It's all very confusing to me because I thought Apple's assembler
>*was* gas.

Sort of - if I understand it correctly, it is set of separately
maintained patches (for Mach-O) to an old version of gas. It is most
conveniently thought of as a different assembler. Not that it matters,
as the syntax and pseudo-ops supported by gas itself vary between
platforms, as the aim is to behave as the native assembler.

If you care, you could look at the cctools sources - they are publically
available.

Jeffrey Scofield

unread,
May 1, 2009, 6:12:42 PM5/1/09
to caml...@inria.fr
Nathaniel Gray <n8g...@gmail.com> writes:

> Speaking of which, has anybody built an ocaml cross compiler for the
> iphone that can work with native cocoa touch apps built with the
> official SDK? It's probably too late for my current project but in
> the future I'd love to use ocaml for my iPhone projects. I tried
> following the instructions here[1] with some necessary
> modifications[2] to get the assembler to work but my test app crashed
> as soon as it entered ocaml code. I don't know enough about the ARM
> platform to say why.

Yes, we have OCaml 3.10.2 cross compiling for iPhone OS 2.2.

We started from the instructions you mention:

> [1] http://web.yl.is.s.u-tokyo.ac.jp/~tosh/ocaml-on-iphone/

We made the same change to the .global pseudo-ops:

> [2] I had to change all '.global' to '.globl' in arm.s and
> arm/emit.mlp. I have no idea what that signifies.

(These are just variant spellings of the same pseudo-op
for declaring a global symbol. For whatever reason, the
Apple assembler seems to insist on .globl. Other
incarnations of gas seem to allow either spelling.)

There are at least two more problems, however. Presumably
this is due to differences between the iPhone ABI and the one that
the ARM port (the old one I guess you could say) is targeted for.

1. arm.S uses r10 as a scratch register, but it is not a scratch
register on iPhone. It has to be saved/restored when passing
between OCaml and the native iPhone code (I think of it as
ObjC code). Note, by the way, that gdb shows r10 by the
alternate name of sl. This is confusing at first.

2. arm.S assumes r9 can be used as a general purpose register,
but it is used on the iPhone to hold a global thread context.
Again, it has to be saved/restored (or at least that's what we
decided to do).

We saw crashes caused by both of these problems.

I'm appending a new version of arm.S that works for us with
one OCaml thread. (Multiple threads will almost certainly
require more careful handling of r9.) It has the patches
from Toshiyuki Maeda mentioned above and a few of our
own to fix these two problems.

We have an application that has been working well for
a couple months, so there's some evidence that these
changes are sufficient.

We also made a small fix to the ARM code generator
(beyond the patches from Toshiyuki Maeda). In essence,
it fixes up the handling of unboxed floating return
values of external functions. Things mostly work without
this change; I'll save a description for a later post (if
anybody is interested).

Regards,

Jeff Scofield
Seattle

---------- 8< ---- cut here for arm.S ----- >8 -----
/***********************************************************************/
/* */
/* Objective Caml */
/* */
/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */
/* */
/* Copyright 1998 Institut National de Recherche en Informatique et */
/* en Automatique. All rights reserved. This file is distributed */
/* under the terms of the GNU Library General Public License, with */
/* the special exception on linking described in file ../LICENSE. */
/* */
/***********************************************************************/

/* $Id: arm.S,v 1.15.18.1 2008/02/20 12:25:17 xleroy Exp $ */

/* Linux/BSD with ELF binaries and Solaris do not prefix identifiers with _.
Linux/BSD with a.out binaries and NextStep do.
Copied from asmrun/i386.S */

#if defined(SYS_solaris)
#define CONCAT(a,b) a/**/b
#else
#define CONCAT(a,b) a##b
#endif

#if defined(SYS_linux_elf) || defined(SYS_bsd_elf) \
|| defined(SYS_solaris) || defined(SYS_beos) || defined(SYS_gnu)
#define G(x) x
#define LBL(x) CONCAT(.L,x)
#else
#define G(x) CONCAT(_,x)
#define LBL(x) CONCAT(L,x)
#endif

#if defined(SYS_macosx)
#define global globl
#endif

/* Asm part of the runtime system, ARM processor */

#define trap_ptr r11
#define alloc_ptr r8
#define alloc_limit r9
#define sp r13
#define lr r14
#define pc r15

.text

/* Allocation functions and GC interface */

.global G(caml_call_gc)
G(caml_call_gc):
/* Record return address */
/* We can use r10 as a temp reg since it's not live here */
ldr r10, LBL(caml_last_return_address)
str lr, [r10, #0]
/* Branch to shared GC code */
bl LBL(invoke_gc)
/* Restart allocation sequence (4 instructions before) */
sub lr, lr, #16
mov pc, lr

.global G(caml_alloc1)
G(caml_alloc1):
ldr r10, [alloc_limit, #0]
sub alloc_ptr, alloc_ptr, #8
cmp alloc_ptr, r10
movcs pc, lr /* Return if alloc_ptr >= alloc_limit */
/* Record return address */
ldr r10, LBL(caml_last_return_address)
str lr, [r10, #0]
/* Invoke GC */
bl LBL(invoke_gc)
/* Try again */
b G(caml_alloc1)

.global G(caml_alloc2)
G(caml_alloc2):
ldr r10, [alloc_limit, #0]
sub alloc_ptr, alloc_ptr, #12
cmp alloc_ptr, r10
movcs pc, lr /* Return if alloc_ptr >= alloc_limit */
/* Record return address */
ldr r10, LBL(caml_last_return_address)
str lr, [r10, #0]
/* Invoke GC */
bl LBL(invoke_gc)
/* Try again */
b G(caml_alloc2)

.global G(caml_alloc3)
G(caml_alloc3):
ldr r10, [alloc_limit, #0]
sub alloc_ptr, alloc_ptr, #16
cmp alloc_ptr, r10
movcs pc, lr /* Return if alloc_ptr >= alloc_limit */
/* Record return address */
ldr r10, LBL(caml_last_return_address)
str lr, [r10, #0]
/* Invoke GC */
bl LBL(invoke_gc)
/* Try again */
b G(caml_alloc3)

.global G(caml_allocN)
G(caml_allocN):
str r12, [sp, #-4]!
ldr r12, [alloc_limit, #0]
sub alloc_ptr, alloc_ptr, r10
cmp alloc_ptr, r12
ldr r12, [sp], #4
movcs pc, lr /* Return if alloc_ptr >= alloc_limit */
/* Record return address and desired size */
ldr alloc_limit, LBL(caml_last_return_address)
str lr, [alloc_limit, #0]
ldr alloc_limit, LBL(Lcaml_requested_size)
str r10, [alloc_limit, #0]
/* Invoke GC */
bl LBL(invoke_gc)
/* Try again */
ldr r10, LBL(Lcaml_requested_size)
ldr r10, [r10, #0]
b G(caml_allocN)

/* Shared code to invoke the GC */
LBL(invoke_gc):
/* Record lowest stack address */
ldr r10, LBL(caml_bottom_of_stack)
str sp, [r10, #0]
/* Save integer registers and return address on stack */
stmfd sp!, {r0,r1,r2,r3,r4,r5,r6,r7,r10,r12,lr}
/* Store pointer to saved integer registers in caml_gc_regs */
ldr r10, LBL(caml_gc_regs)
str sp, [r10, #0]
/* Save non-callee-save float registers */
sub sp, sp, #64
fstd d0, [sp, #56]
fstd d1, [sp, #48]
fstd d2, [sp, #40]
fstd d3, [sp, #32]
fstd d4, [sp, #24]
fstd d5, [sp, #16]
fstd d6, [sp, #8]
fstd d7, [sp, #0]
/* Save current allocation pointer for debugging purposes */
ldr r10, LBL(caml_young_ptr)
str alloc_ptr, [r10, #0]
/* Save trap pointer in case an exception is raised during GC */
ldr r10, LBL(caml_exception_pointer)
str trap_ptr, [r10, #0]
/* Restore r9 for iPhoneOS */
ldr r9, LBL(Lcaml_touch_threadctx) /* iPhone */
ldr r9, [r9, #0] /* iPhone */
/* Call the garbage collector */
bl G(caml_garbage_collection)
/* Restore the registers from the stack */
fldd d7, [sp, #0]
fldd d6, [sp, #8]
fldd d5, [sp, #16]
fldd d4, [sp, #24]
fldd d3, [sp, #32]
fldd d2, [sp, #40]
fldd d1, [sp, #48]
fldd d0, [sp, #56]
add sp, sp, #64
ldmfd sp!, {r0,r1,r2,r3,r4,r5,r6,r7,r10,r12}
/* Reload return address */
ldr r10, LBL(caml_last_return_address)
ldr lr, [r10, #0]
/* Say that we are back into Caml code */
mov alloc_ptr, #0
str alloc_ptr, [r10, #0]
/* Reload new allocation pointer and allocation limit */
ldr r10, LBL(caml_young_ptr)
ldr alloc_ptr, [r10, #0]
ldr alloc_limit, LBL(caml_young_limit)
/* Return to caller */
ldmfd sp!, {pc}

/* Call a C function from Caml */
/* Function to call is in r10 */

.global G(caml_c_call)
G(caml_c_call):
/* Preserve return address in callee-save register r4 */
mov r4, lr
/* Record lowest stack address and return address */
ldr r5, LBL(caml_last_return_address)
ldr r6, LBL(caml_bottom_of_stack)
str lr, [r5, #0]
str sp, [r6, #0]
/* Make the exception handler and alloc ptr available to the C code */
ldr r6, LBL(caml_young_ptr)
ldr r7, LBL(caml_exception_pointer)
str alloc_ptr, [r6, #0]
str trap_ptr, [r7, #0]
ldr r9, LBL(Lcaml_touch_threadctx) /* iPhone */
ldr r9, [r9, #0] /* iPhone */
/* Call the function */
mov lr, pc
mov pc, r10
/* Reload alloc ptr */
ldr alloc_ptr, [r6, #0] /* r6 still points to caml_young_ptr */
/* Say that we are back into Caml code */
mov r6, #0
str r6, [r5, #0] /* r5 still points to caml_last_return_address */
/* Return */
mov pc, r4

/* Start the Caml program */

.global G(caml_start_program)
G(caml_start_program):
stmfd sp!, {r10}
ldr r10, LBL(Lcaml_touch_threadctx) /* iPhone */
str r9, [r10, #0] /* iPhone */
ldr r10, LBL(caml_program)

/* Code shared with caml_callback* */
/* Address of Caml code to call is in r10 */
/* Arguments to the Caml code are in r0...r3 */

LBL(jump_to_caml):
/* Save return address and callee-save registers */
stmfd sp!, {r4,r5,r6,r7,r8,r9,r11,lr}
sub sp, sp, #64
fstd d15, [sp, #56]
fstd d14, [sp, #48]
fstd d13, [sp, #40]
fstd d12, [sp, #32]
fstd d11, [sp, #24]
fstd d10, [sp, #16]
fstd d9, [sp, #8]
fstd d8, [sp, #0]
/* Setup a callback link on the stack */
sub sp, sp, #(4*3)
ldr r4, LBL(caml_bottom_of_stack)
ldr r4, [r4, #0]
str r4, [sp, #0]
ldr r4, LBL(caml_last_return_address)
ldr r4, [r4, #0]
str r4, [sp, #4]
ldr r4, LBL(caml_gc_regs)
ldr r4, [r4, #0]
str r4, [sp, #8]
/* Setup a trap frame to catch exceptions escaping the Caml code */
sub sp, sp, #(4*2)
ldr r4, LBL(caml_exception_pointer)
ldr r4, [r4, #0]
str r4, [sp, #0]
ldr r4, LBL(Ltrap_handler)
str r4, [sp, #4]
mov trap_ptr, sp
/* Reload allocation pointers */
ldr r4, LBL(caml_young_ptr)
ldr alloc_ptr, [r4, #0]
ldr alloc_limit, LBL(caml_young_limit)
/* We are back into Caml code */
ldr r4, LBL(caml_last_return_address)
mov r5, #0
str r5, [r4, #0]
/* Call the Caml code */
mov lr, pc
mov pc, r10
LBL(caml_retaddr):
/* Pop the trap frame, restoring caml_exception_pointer */
ldr r4, LBL(caml_exception_pointer)
ldr r5, [sp, #0]
str r5, [r4, #0]
add sp, sp, #(2 * 4)
/* Pop the callback link, restoring the global variables */
LBL(return_result):
ldr r4, LBL(caml_bottom_of_stack)
ldr r5, [sp, #0]
str r5, [r4, #0]
ldr r4, LBL(caml_last_return_address)
ldr r5, [sp, #4]
str r5, [r4, #0]
ldr r4, LBL(caml_gc_regs)
ldr r5, [sp, #8]
str r5, [r4, #0]
add sp, sp, #(4*3)
/* Update allocation pointer */
ldr r4, LBL(caml_young_ptr)
str alloc_ptr, [r4, #0]
/* Reload callee-save registers and return */
fldd d8, [sp, #0]
fldd d9, [sp, #8]
fldd d10, [sp, #16]
fldd d11, [sp, #24]
fldd d12, [sp, #32]
fldd d13, [sp, #40]
fldd d14, [sp, #48]
fldd d15, [sp, #56]
add sp, sp, #64
ldmfd sp!, {r4,r5,r6,r7,r8,r9,r11,lr}
ldmfd sp!, {r10}
mov pc, lr

/* The trap handler */
LBL(trap_handler):
/* Save exception pointer */
ldr r4, LBL(caml_exception_pointer)
str trap_ptr, [r4, #0]
/* Encode exception bucket as an exception result */
orr r0, r0, #2
/* Return it */
b LBL(return_result)

/* Raise an exception from C */

.global G(caml_raise_exception)
G(caml_raise_exception):
/* Reload Caml allocation pointers */
ldr r1, LBL(caml_young_ptr)
ldr alloc_ptr, [r1, #0]
ldr alloc_limit, LBL(caml_young_limit)
/* Say we're back into Caml */
ldr r1, LBL(caml_last_return_address)
mov r2, #0
str r2, [r1, #0]
/* Cut stack at current trap handler */
ldr r1, LBL(caml_exception_pointer)
ldr sp, [r1, #0]
/* Pop previous handler and addr of trap, and jump to it */
ldmfd sp!, {trap_ptr, pc}

/* Callback from C to Caml */

.global G(caml_callback_exn)
G(caml_callback_exn):
/* Initial shuffling of arguments (r0 = closure, r1 = first arg) */
stmfd sp!, {r10}
mov r10, r0
mov r0, r1 /* r0 = first arg */
mov r1, r10 /* r1 = closure environment */
ldr r10, [r10, #0] /* code pointer */
b LBL(jump_to_caml)

.global G(caml_callback2_exn)
G(caml_callback2_exn):
/* Initial shuffling of arguments (r0 = closure, r1 = arg1, r2 = arg2) */
stmfd sp!, {r10}
mov r10, r0
mov r0, r1 /* r0 = first arg */
mov r1, r2 /* r1 = second arg */
mov r2, r10 /* r2 = closure environment */
ldr r10, LBL(caml_apply2)
b LBL(jump_to_caml)

.global G(caml_callback3_exn)
G(caml_callback3_exn):
/* Initial shuffling of arguments */
/* (r0 = closure, r1 = arg1, r2 = arg2, r3 = arg3) */
stmfd sp!, {r10}
mov r10, r0
mov r0, r1 /* r0 = first arg */
mov r1, r2 /* r1 = second arg */
mov r2, r3 /* r2 = third arg */
mov r3, r10 /* r3 = closure environment */
ldr r10, LBL(caml_apply3)
b LBL(jump_to_caml)

.global G(caml_ml_array_bound_error)
G(caml_ml_array_bound_error):
/* Load address of [caml_array_bound_error] in r10 */
ldr r10, LBL(caml_array_bound_error)
/* Call that function */
b G(caml_c_call)

/* Global references */

LBL(caml_last_return_address): .long G(caml_last_return_address)
LBL(caml_bottom_of_stack): .long G(caml_bottom_of_stack)
LBL(caml_gc_regs): .long G(caml_gc_regs)
LBL(caml_young_ptr): .long G(caml_young_ptr)
LBL(caml_young_limit): .long G(caml_young_limit)
LBL(caml_exception_pointer): .long G(caml_exception_pointer)
LBL(caml_program): .long G(caml_program)
LBL(Ltrap_handler): .long LBL(trap_handler)
LBL(caml_apply2): .long G(caml_apply2)
LBL(caml_apply3): .long G(caml_apply3)
LBL(Lcaml_requested_size): .long LBL(caml_requested_size)
LBL(caml_array_bound_error): .long G(caml_array_bound_error)
LBL(Lcaml_touch_threadctx): .long LBL(caml_touch_threadctx)

data
LBL(caml_requested_size): .long 0
LBL(caml_touch_threadctx): .long 0

/* GC roots for callback */

.data

.global G(caml_system__frametable)
G(caml_system__frametable):
.long 1 /* one descriptor */
.long LBL(caml_retaddr) /* return address into callback */
.short -1 /* negative frame size => use callback link */
.short 0 /* no roots */
.align 2

#if defined(SYS_macosx)
.text
.global G(__stub__modsi3)
G(__stub__modsi3):
b LBL(__stub__modsi3)
.global G(__stub__divsi3)
G(__stub__divsi3):
b LBL(__stub__divsi3)

.section __TEXT,__picsymbolstub4,symbol_stubs,none,16
.align 2
LBL(__stub__modsi3):
.indirect_symbol G(__modsi3)
ldr ip, LBL(__stub__modsi3$slp)
LBL(__stub__modsi3$scv):
add ip, pc, ip
ldr pc, [ip, #0]
LBL(__stub__modsi3$slp):
.long LBL(__stub__modsi3$lazy_ptr) - (LBL(__stub__modsi3$scv) + 8)
.lazy_symbol_pointer
LBL(__stub__modsi3$lazy_ptr):
.indirect_symbol G(__modsi3)
.long dyld_stub_binding_helper

.section __TEXT,__picsymbolstub4,symbol_stubs,none,16
.align 2
LBL(__stub__divsi3):
.indirect_symbol G(__divsi3)
ldr ip, LBL(__stub__divsi3$slp)
LBL(__stub__divsi3$scv):
add ip, pc, ip
ldr pc, [ip, #0]
LBL(__stub__divsi3$slp):
.long LBL(__stub__divsi3$lazy_ptr) - (LBL(__stub__divsi3$scv) + 8)
.lazy_symbol_pointer
LBL(__stub__divsi3$lazy_ptr):
.indirect_symbol G(__divsi3)
.long dyld_stub_binding_helper

.subsections_via_symbols
#endif

Nathaniel Gray

unread,
May 1, 2009, 8:07:37 PM5/1/09
to Jeffrey Scofield, caml...@inria.fr
On Fri, May 1, 2009 at 3:12 PM, Jeffrey Scofield <dynas...@mac.com> wrote:
> Nathaniel Gray <n8g...@gmail.com> writes:
>
>> Speaking of which, has anybody built an ocaml cross compiler for the
>> iphone that can work with native cocoa touch apps built with the
>> official SDK?  It's probably too late for my current project but in
>> the future I'd love to use ocaml for my iPhone projects.  I tried
>> following the instructions here[1] with some necessary
>> modifications[2] to get the assembler to work but my test app crashed
>> as soon as it entered ocaml code.  I don't know enough about the ARM
>> platform to say why.
>
> Yes, we have OCaml 3.10.2 cross compiling for iPhone OS 2.2.

Great!

> There are at least two more problems, however.  Presumably
> this is due to differences between the iPhone ABI and the one that
> the ARM port (the old one I guess you could say) is targeted for.
>
> 1.  arm.S uses r10 as a scratch register, but it is not a scratch
>    register on iPhone.  It has to be saved/restored when passing
>    between OCaml and the native iPhone code (I think of it as
>    ObjC code).  Note, by the way, that gdb shows r10 by the
>   alternate name of sl.  This is confusing at first.
>
> 2. arm.S assumes r9 can be used as a general purpose register,
>    but it is used on the iPhone to hold a global thread context.
>   Again, it has to be saved/restored (or at least that's what we
>   decided to do).
>
> We saw crashes caused by both of these problems.

Ok, I'm glad I left this to people who are familiar with ARM assembly
programming. :-)

> I'm appending a new version of arm.S that works for us with
> one OCaml thread.  (Multiple threads will almost certainly
> require more careful handling of r9.)  It has the patches
> from Toshiyuki Maeda mentioned above and a few of our
> own to fix these two problems.

Awesome, but now I'm confused because the arm.S you included has lots
of .global pseudo-ops. Do you not compile it with Apple's as?

> We have an application that has been working well for
> a couple months, so there's some evidence that these
> changes are sufficient.

What's your app? How are you managing the interface between Cocoa and OCaml?

> We also made a small fix to the ARM code generator
> (beyond the patches from Toshiyuki Maeda).  In essence,
> it fixes up the handling of unboxed floating return
> values of external functions.  Things mostly work without
> this change; I'll save a description for a later post (if
> anybody is interested).

I am very interested in any and all information needed to get a
correct OCaml port suitable for use in App Store applications. Please
share!

BTW, I've added an issue in mantis[1] now that I know this is more
than a configuration problem.

Thanks,
-n8

[1] http://caml.inria.fr/mantis/view.php?id=4782

_______________________________________________

Jeffrey Scofield

unread,
May 2, 2009, 7:15:30 PM5/2/09
to caml...@inria.fr
Nathaniel Gray <n8g...@gmail.com> writes:

> Ok, I'm glad I left this to people who are familiar with ARM
> assembly programming. :-)

We've done a lot of assembly programming, but none of us is an
ARM expert. We looked at ARM documents and the assembly (.s)
files generated by ocamlopt and gcc, and spent some long sessions
with gdb.

> Awesome, but now I'm confused because the arm.S you included
> has lots of .global pseudo-ops. Do you not compile it with
> Apple's as?

At around line 36, you'll see:

#define global globl

As I said in private mail, you could call this a hack, but it's a
way to avoid making lots of small changes everywhere in the file.

> What's your app?

We're working on a collection of card games for casual play.

> How are you managing the interface between Cocoa and OCaml?

This is a big topic. The summary is that we model Cocoa objects
as OCaml objects. We have a layer that wraps OCaml objects in
smallish ObjC objects for use on the ObjC side, and wraps ObjC
objects in smallish OCaml objects for use on the OCaml side. The
layer then translates between these representations as required
for calls into iPhoneOS and Cocoa Touch from OCaml (asking for
iPhone OS services) and into OCaml from iPhoneOS (for event
handling).

> > We also made a small fix to the ARM code generator
>

> I am very interested in any and all information needed to get a
> correct OCaml port suitable for use in App Store applications.
> Please share!

OK, I'll gather up our patch and send it to the list. I want to
separate out our changes from those of Toshiyuki Maeda [1].

As I said, our patch fixes calls to external C float functions
such as floor(), sin(), and so on. There is special handling in
ocamlopt to allow them to be unboxed, but the ABI of the existing
ARM code generator doesn't match the iPhone ABI.

Regards,

Jeff Scofield
Seattle

[1] http://web.yl.is.s.u-tokyo.ac.jp/~tosh/ocaml-on-iphone/

Robert Muller

unread,
May 3, 2009, 8:34:26 AM5/3/09
to Jeffrey Scofield, caml...@inria.fr
This sounds great. I will be teaching an iphone programming course
next year and I would
very much like to use the course as an opportunity to introduce
students to caml. I know that
there are others gearing up for iphone programming courses who aren't
thrilled with the idea
of teaching Objective C.

If you were to post your resources on a web site it might lower the
barrier to entry for more
people to use ocaml + your wrappers rather than Objective C.

Bob Muller

Jeffrey Scofield

unread,
May 5, 2009, 12:59:57 AM5/5/09
to caml...@inria.fr
Robert Muller <mul...@cs.bc.edu> writes:

> This sounds great. I will be teaching an iphone programming
> course next year and I would very much like to use the course
> as an opportunity to introduce students to caml. I know that
> there are others gearing up for iphone programming courses who
> aren't thrilled with the idea of teaching Objective C.

Right now we're mostly focused on getting iPhone applications
completed and accepted by Apple. We've built the interface layer
by hand, a little bit at a time as required. So there are
wrappers only for the parts of Cocoa Touch we use, and there are
a few rough edges. It wouldn't make a good teaching environment
in its current form.

The cross-compiler does work though, and it builds working
applications. I'll be sending the rest of our patches shortly.
Creating wrappers for all of Cocoa Touch would be a very big job
but it might be possible to implement a small subset for
students.

> If you were to post your resources on a web site it might lower
> the barrier to entry for more people to use ocaml + your
> wrappers rather than Objective C.

Right now the best we can do is probably to offer advice on some
things that did and didn't work for us. As we make progress
perhaps we'll be in a position to do more.

Regards,

Jeff Scofield
Seattle

Xavier Leroy

unread,
May 5, 2009, 5:43:31 AM5/5/09
to Joel Reymont, O'Caml Mailing List
Joel Reymont wrote:

> Is the ARM backend (ocamlopt) usable and actively maintained?

In brief: yes modulo ABI issues; yes.

In more details:

In OCaml 3.11 and earlier, the ARM port uses an old ABI (software
conventions on using registers, etc). This ABI corresponds to the
"arm" port of Debian; I don't know about other Linux distros.
OCaml/ARM works like a charm on platforms supported by Debian/arm.
I use it on a Linksys NSLU2.

However, most embedded Linux/ARM platforms use a more recent,
incompatible ABI called EABI. In Debian Lenny, it's available under
the name "armel".

I recently revised the OCaml/ARM port to adapt it to EABI and to
software floating-point emulation. You can find it in the CVS trunk,
and testing and feedback is most welcome. It works fine under Debian
Lenny "armel".

Floating-point performance is better than with the old port, because
the latter used floating-point instructions that are no longer
available on contemporary ARM processors and therefore had to be
trapped and emulated by the kernel. In contrast, with soft
floating-point, emulation is performed in user land by C library
functions, which can also take advantage of vector float
instructions if the processor supports them.

Concerning the iPhone, it is not supported out of the box by 3.11 nor
by the CVS trunk code. For 3.11, several patches have been mentioned
on this list; it would be great if someone with iPhone development
experience could combine them and publish a unified patch.

For the CVS trunk code, it seems we are getting close: as far as I
could see, MacOSX/ARM uses EABI plus Apple's "signature" approach to
dynamic linking. However, I haven't yet succeeded in running Apple's
iPhone SDK compilers from the command-line. (It looks like one of
those Microsoft SDK's that assume everyone is developing from the
vendor-supplied IDE...) Again, I welcome feedback and patches from
iPhone development experts.

- Xavier Leroy

Jeffrey Scofield

unread,
May 5, 2009, 11:56:26 PM5/5/09
to caml...@inria.fr
Xavier Leroy <Xavier...@inria.fr> writes:

> Concerning the iPhone, it is not supported out of the box by
> 3.11 nor by the CVS trunk code. For 3.11, several patches have
> been mentioned on this list; it would be great if someone with
> iPhone development experience could combine them and publish a
> unified patch.

I'm happy to provide a unified patch containing everything
we use to cross-compile OCaml for iPhone. Note that our
patches are against OCaml 3.10.2. This is simpler for us because
we started with patches by Toshiyuki Maeda that are for 3.10.2.
I would imagine that the changes for 3.11 are minimal, but we
haven't tried it yet. When we move to 3.11, I'd be happy to
provide new patches (if nobody else does so earlier).

> For the CVS trunk code, it seems we are getting close: as far
> as I could see, MacOSX/ARM uses EABI plus Apple's "signature"
> approach to dynamic linking. However, I haven't yet succeeded
> in running Apple's iPhone SDK compilers from the command-line.
> (It looks like one of those Microsoft SDK's that assume
> everyone is developing from the vendor-supplied IDE...) Again,

> welcome feedback and patches from iPhone development experts.

Yes, Apple assumes all developers use their IDE, Xcode. You can
extract working command lines from the Xcode build log,
painfully.

Here's a little script that shows how we run the cross-compiling
version of gcc. Although Nathaniel Gray has already posted his,
it might be helpful to have two independent sets.

This is for compiling to the iPhoneOS 2.2 environment.
Differences for other environments are straightforward.

#!/bin/sh
PLATFORM=/Developer/Platforms/iPhoneOS.platform
SDK=/Developer/SDKs/iPhoneOS2.2.sdk
CC="$PLATFORM/Developer/usr/bin/gcc -arch armv6 -isysroot $PLATFORM/$SDK"
$CC "$@"

Regards,

Jeff Scofield
Seattle

Reply all
Reply to author
Forward
0 new messages