[MLton-devel] minor nits with new compiler

Matthew Fluet Matthew Fluet <fluet@CS.Cornell.EDU>
Fri, 12 Apr 2002 09:22:12 -0400 (EDT)


> Any  way,  why  is  libgmp being pulled in?  Thie mseans that even code which
> does not use IntInf will require the gmp shared library to be  installed  not
> only in the compilers machine, but in the users machine.

[fluet@lennon temp]$ cat z.sml
val _ = print "Hello World\n";
[fluet@lennon temp]$ mlton -keep o z.sml 
[fluet@lennon temp]$ nm z.0.o z.o  | grep U
         U C_CS_sub
         U GC_gc
         U MLton_allocTooLarge
         U MLton_bug
         U MLton_bug_msg
         U MLton_exit
         U Posix_Error_getErrno
         U Posix_Error_strerror
         U Posix_IO_write
         U Posix_ProcEnv_isatty
         U Stdio_print
         U cReturnTempL
         U c_stackP
         U gcState
         U globalint
         U globalpointer
         U globalpointerNonRoot
         U localint
         U localpointer
         U F_0
         U GC_createStrings
         U IntInf_init
         U MLton_init
         U sfread
         U swrite

So, the short answer is because IntInf_init isn't being eliminated by gcc
when it compiles the .c stub.

>From x86codegen.h:
	if (gcState.isOriginal) {					\
		/* The (> 1) check is so that the C compiler can \
		 * eliminate the call if there are no IntInfs and we	\
		 * then won't have to link in with the IntInf stuff.	\
		 */							\
		if (cardof(intInfInits) > 1)				\
			IntInf_init(&gcState, intInfInits);		\

Looking at the .s of the compiled .c:
	cmpl $0,gcState+544 # this is the gcState.isOriginal test
	je .L32
	jmp .L33
	addl $-8,%esp
	pushl $intInfInits
	pushl $gcState
	call IntInf_init
	addl $16,%esp
.L33:

The call to IntInf_init is clearly dead code.  The issue seems to be that
when we compile the .c stub, we don't pass enough optimization options to
eliminate the call to IntInf_init.  We don't have this problem when
compiling with -native false.

The problem is with compileC in src/mlton/main.sml:
		  fun compileC (cFile: File.t,
				sFiles: File.t list) =
		     let
			val switches =
			   List.concat
			   [["-S"],
			    if !debug then ["-g"] else [],
			    definesAndIncludes,
			    if !Native.native
			       then []
			    else
			    List.concat
			    [[concat ["-O", Int.toString (!optimization)]],
			     gccSwitches]]

When compiling -native true, we don't pass any optimization options to
gcc.  It wouldn't seem as though there is any harm is using the full set
of options on the .c stub (although there is virtually no code there at
all, so it's not really going to do much), but at a minimum, we need to
pass -O1 for dead-code elimination to remove the call to IntInf_init.

I checked in a new main.sml that lifts the -O switch to being common in
both -native true and -native false.  That seems to fix the problem (so
long as you don't compile with -O0).


> The  weird  thing is that it doesn't really need any thing from libgmp.so.  I
> made a libgmp.a which had no .o files in it and added
>     -L .
> to the mlton line, and got no missing externals and an executable which does
> NOT  depend on libgmp.so, and it works fine.  If the linker adds a dependency
> on for all shared libraries mentioned, even those which  contribute nothing,
> then MLton will have to be made smart enough to drop the
>     -lgmp
> argument if it doesn't need any thing from libgmp.  Definitely a pain.

This suggests an alternative solution.  We're going to pull in IntInf_init
no matter what, but that function doesn't really depend on libgmp.so.  So,
it should also be sufficient to break IntInf_init out of IntInf.c so that
it ends up in it's own object file in libmlton.a.  Then when we pull
IntInf_init into the executable, we won't pull in any dependencies on
libgmp.so.  Considering how fine-grained we've split up all of the
runtime/basis files, this probably isn't a bad idea.


_______________________________________________
MLton-devel mailing list
MLton-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mlton-devel