[MLton] Semantics of giving a .c file to mlton?
Matthew Fluet
fluet at tti-c.org
Thu Oct 23 09:34:47 PDT 2008
On Thu, 23 Oct 2008, Ryan Newton wrote:
> This is perhaps an undocumented bit of functionality, but I frequently
> enjoy passing .c files to mlton directly, rather than compiling them
> to .o files first.
Yes, that is supported.
> Consider the two small files attached below. They will compile as follows:
>
> mlton -default-ann 'allowFFI true' export.sml export.c
>
> I was (probably erroneously) under the impression that I didn't need
> to do -export-header, and #include the resulting file if I was passing
> in .c files directly (mlton could do that for me). Well, the above
> compiles fine and runs fine on a 32 bit platform:
>
> Running ML program...
> Inside C program... calling back to ML
> Got ML array: 0xb7fd2f98
> Set first element
>
> But on 64 bit platforms it the call back into ML *completes* but
> returns a bogus address, then writing to that bogus address segfaults.
>
> Running ML program...
> Inside C program... calling back to ML
> Got ML array: 0xffffffff910996a8
> Segmentation fault
>
> Exporting the header and including it in the .c file fixes the problem
> on 64-bit machines. I can do it that way but it would be awfully nice
> to officially be able to do what I happen to get away with on 32-bit
> platforms.
>
> Is this all as intended?
When MLton invokes gcc on a .c file, it does so with '-w' to supress all
warnings. This is because MLton invokes gcc on generated .c files, which,
while mostly warning free, would have some spurious warnings that we don't
want to bother the user. However, this means that your export.c file is
being compiled with '-w', and so you are not getting the warning about the
implicit declaration of ARRAYALLOC_CHAR. In the absence of a declaration,
gcc introduces the implicit declaration:
int ARRAYALLOC_CHAR(...);
assuming that ARRAYALLOC_CHAR returns int (and admitting any number and
types of arguments to ARRAYALLOC_CHAR).
It happens to work for a 32-bit platform because the C calling convention
for returning (a 32-bit) void* is the same for returning (a 32-bit) int.
It fails to work on for a 64-bit platform because the C calling convention
for returning (a 64-bit) void* is different from returning a (32-bit) int.
More information about the MLton
mailing list