[MLton-commit] r4718

Matthew Fluet fluet at mlton.org
Thu Oct 5 09:41:30 PDT 2006


Moved the jumpToSML/returnToC code from x86-main.h to x86-codegen.fun.

This code essentially establishes the interface by which C jumps into
SML code (both initially and for exported SML functions) and by which
SML returns to C (for exported SML functions).  The key property is
that all C activation frames must be accounted for on the C stack.
Each time C jumps to SML via jumpToSML, the current C stack pointer
is saved for C calls from SML.  Additionally, we ensure that the saved
C stack pointer is 16-byte aligned.

Previously, this logic was handled in x86-main.h via inline assembly.
This had a number of disadvantages:
 1. We couldn't be sure of what gcc was doing with %esp before the
inline assembly began.  In fact, we couldn't be sure that %esp
necessarily pointed to the top of the C stack.
 2. We needed extra logic from CPP and from MLton_main arguments to
determine whether or not %esp was reserved for sigstack handling and
whether or not extra "_" were required by assembly labels.

Moving the definition of this code to x86-codegen.fun solves these
problems:
 1. Since we control the entire execution, we know that %esp is
16-aligned on entry (modulo the return address pushed by the call
instruction) and can maintain this property easily.
 2. We can save temporaries in the C stack frame corresponding to the
call to MLton_jumpToC.
 3. We know whether or not to reserve %esp and whether or not labels
need an extra "_".

The downside is that writing out the assembly via the datatype
interface is much more verbose.


----------------------------------------------------------------------

U   mlton/trunk/include/x86-main.h
U   mlton/trunk/mlton/codegen/x86-codegen/x86-codegen.fun
U   mlton/trunk/mlton/codegen/x86-codegen/x86-mlton-basic.sig

----------------------------------------------------------------------

Modified: mlton/trunk/include/x86-main.h
===================================================================
--- mlton/trunk/include/x86-main.h	2006-10-05 01:37:54 UTC (rev 4717)
+++ mlton/trunk/include/x86-main.h	2006-10-05 16:41:15 UTC (rev 4718)
@@ -50,63 +50,12 @@
 #define DEBUG_X86CODEGEN FALSE
 #endif
 
-#if (defined (__CYGWIN__) || defined (__Darwin__) || defined (__MSVCRT__))
-#define ReturnToC "_Thread_returnToC"
-#elif (defined (__FreeBSD__) || defined (__linux__) || defined (__NetBSD__) || defined (__OpenBSD__) || defined (__sun__))
-#define ReturnToC "Thread_returnToC"
-#else
-#error ReturnToC not defined
-#endif
-
 static Word32 returnAddressToFrameIndex (Word32 w) {
         return *((Word32*)(w - sizeof(Word32)));
 }
 
-#define Main(al, mg, mfs, mmc, pk, ps, ml, reserveEsp)                  \
-void MLton_jumpToSML (pointer jump) {                                   \
-        Word c_stackPLast;                                              \
-        Word c_stackPLastTrue;                                          \
-                                                                        \
-        if (DEBUG_X86CODEGEN)                                           \
-                fprintf (stderr, "MLton_jumpToSML(0x%08x) starting\n", (uint)jump); \
-        c_stackPLast = c_stackP;                                        \
-        c_stackPLastTrue = c_stackPTrue;                                \
-        if (reserveEsp)                                                 \
-                __asm__ __volatile__                                    \
-                ("pusha\n\t"                                            \
-                 "movl %%esp,%0\n\t"                                    \
-                 "andl $-16,%%esp\n\t"                                  \
-                 "movl %%esp,%1\n\t"                                    \
-                 "movl %2,%%ebp\n\t"                                    \
-                 "movl %3,%%edi\n\t"                                    \
-                 "jmp *%4\n"                                            \
-                 ".global "ReturnToC"\n"ReturnToC":\n\t"                \
-                 "movl %0,%%esp\n\t"                                    \
-                 "popa\n"                                               \
-                 : "=o" (c_stackPTrue), "=o" (c_stackP)                 \
-                : "o" (gcState.stackTop), "o" (gcState.frontier), "r" (jump) \
-                );                                                      \
-        else                                                            \
-                __asm__ __volatile__                                    \
-                ("pusha\n\t"                                            \
-                 "movl %%esp,%0\n\t"                                    \
-                 "andl $-16,%%esp\n\t"                                  \
-                 "movl %%esp,%1\n\t"                                    \
-                 "movl %2,%%ebp\n\t"                                    \
-                 "movl %3,%%esp\n\t"                                    \
-                 "jmp *%4\n"                                            \
-                 ".global "ReturnToC"\n"ReturnToC":\n\t"                \
-                 "movl %0,%%esp\n\t"                                    \
-                 "popa\n"                                               \
-                 : "=o" (c_stackPTrue), "=o" (c_stackP)                 \
-                : "o" (gcState.stackTop), "o" (gcState.frontier), "r" (jump) \
-                );                                                      \
-        c_stackP = c_stackPLast;                                        \
-        c_stackPTrue = c_stackPLastTrue;                                \
-        if (DEBUG_X86CODEGEN)                                           \
-                fprintf (stderr, "MLton_jumpToSML(0x%08x) done\n", (uint)jump); \
-        return;                                                         \
-}                                                                       \
+#define Main(al, mg, mfs, mmc, pk, ps, ml)                              \
+void MLton_jumpToSML (pointer jump);                                    \
 void MLton_callFromC () {                                               \
         pointer jump;                                                   \
         GC_state s;                                                     \

Modified: mlton/trunk/mlton/codegen/x86-codegen/x86-codegen.fun
===================================================================
--- mlton/trunk/mlton/codegen/x86-codegen/x86-codegen.fun	2006-10-05 01:37:54 UTC (rev 4717)
+++ mlton/trunk/mlton/codegen/x86-codegen/x86-codegen.fun	2006-10-05 16:41:15 UTC (rev 4718)
@@ -62,12 +62,6 @@
   structure x86Validate
     = x86Validate (structure x86 = x86)
 
-  structure C =
-    struct
-      val truee = "TRUE"
-      val falsee = "FALSE"
-    end
-
   open x86
   fun output {program as Machine.Program.T {chunks, frameLayouts, handlesSignals,
                                             main, ...},
@@ -137,7 +131,7 @@
                           then String.dropPrefix (mainLabel, 1)
                        else mainLabel
                  in
-                    [mainLabel, if reserveEsp then C.truee else C.falsee]
+                    [mainLabel]
                  end
               fun declareLocals () =
                  List.foreach
@@ -179,6 +173,174 @@
              x86.Assembly.label x86MLton.fileNameLabel,
              x86.Assembly.pseudoop_string [file]]
 
+        fun outputJumpToSML print =
+           let
+              val jumpToSML = x86.Label.fromString "MLton_jumpToSML"
+              val returnToC = x86.Label.fromString "Thread_returnToC"
+              val {frontierReg, stackTopReg} =
+                 if reserveEsp
+                    then {frontierReg = x86.Register.edi,
+                          stackTopReg = x86.Register.ebp}
+                    else {frontierReg = x86.Register.esp,
+                          stackTopReg = x86.Register.ebp}
+              val asm =
+                 [
+                  x86.Assembly.pseudoop_text (),
+                  x86.Assembly.pseudoop_p2align 
+                  (x86.Immediate.const_int 4, NONE, NONE),
+                  x86.Assembly.pseudoop_global jumpToSML,
+                  x86.Assembly.label jumpToSML,
+                  x86.Assembly.instruction_binal
+                  {oper = x86.Instruction.SUB,
+                   src = x86.Operand.immediate_const_int 28,
+                   dst = x86.Operand.register x86.Register.esp,
+                   size = x86.Size.LONG},
+                  x86.Assembly.instruction_mov
+                  {src = (x86.Operand.address o x86.Address.T)
+                         {disp = SOME (x86.Immediate.const_int 32),
+                          base = SOME x86.Register.esp,
+                          index= NONE, scale = NONE},
+                   dst = x86.Operand.register x86.Register.eax,
+                   size = x86.Size.LONG},
+                  x86.Assembly.instruction_mov
+                  {src = x86.Operand.register x86.Register.ebp,
+                   dst = (x86.Operand.address o x86.Address.T)
+                         {disp = SOME (x86.Immediate.const_int 24),
+                          base = SOME x86.Register.esp,
+                          index= NONE, scale = NONE},
+                   size = x86.Size.LONG},
+                  x86.Assembly.instruction_mov
+                  {src = x86.Operand.register x86.Register.ebx,
+                   dst = (x86.Operand.address o x86.Address.T)
+                         {disp = SOME (x86.Immediate.const_int 20),
+                          base = SOME x86.Register.esp,
+                          index= NONE, scale = NONE},
+                   size = x86.Size.LONG},
+                  x86.Assembly.instruction_mov
+                  {src = x86.Operand.register x86.Register.edi,
+                   dst = (x86.Operand.address o x86.Address.T)
+                         {disp = SOME (x86.Immediate.const_int 16),
+                          base = SOME x86.Register.esp,
+                          index= NONE, scale = NONE},
+                   size = x86.Size.LONG},
+                  x86.Assembly.instruction_mov
+                  {src = x86.Operand.register x86.Register.esi,
+                   dst = (x86.Operand.address o x86.Address.T)
+                         {disp = SOME (x86.Immediate.const_int 12),
+                          base = SOME x86.Register.esp,
+                          index = NONE, scale = NONE},
+                   size = x86.Size.LONG},
+                  x86.Assembly.instruction_mov
+                  {src = (x86.Operand.address o x86.Address.T)
+                         {disp = SOME (x86.Immediate.label x86MLton.c_stackP),
+                          base = NONE, index = NONE, scale = NONE},
+                   dst = x86.Operand.register x86.Register.ebx,
+                   size = x86.Size.LONG},
+                  x86.Assembly.instruction_mov
+                  {src = x86.Operand.register x86.Register.ebx,
+                   dst = (x86.Operand.address o x86.Address.T)
+                         {disp = SOME (x86.Immediate.const_int 8),
+                          base = SOME x86.Register.esp,
+                          index = NONE, scale = NONE},
+                   size = x86.Size.LONG},
+                  x86.Assembly.instruction_mov
+                  {src = x86.Operand.register x86.Register.esp,
+                   dst = (x86.Operand.address o x86.Address.T)
+                         {disp = SOME (x86.Immediate.label x86MLton.c_stackP),
+                          base = NONE, index = NONE, scale = NONE},
+                   size = x86.Size.LONG},
+                  x86.Assembly.instruction_mov
+                  {src = (x86.Operand.address o x86.Address.T)
+                         {disp = (SOME o x86.Immediate.binexp)
+                                 {oper = x86.Immediate.Addition,
+                                  exp1 = x86.Immediate.label x86MLton.gcState_label,
+                                  exp2 = x86.Immediate.const_int 
+                                         (Bytes.toInt 
+                                          (Machine.Runtime.GCField.offset
+                                           Machine.Runtime.GCField.StackTop))},
+                          base = NONE, index = NONE, scale = NONE},
+                   dst = x86.Operand.register stackTopReg,
+                   size = x86.Size.LONG},
+                  x86.Assembly.instruction_mov
+                  {src = (x86.Operand.address o x86.Address.T)
+                         {disp = (SOME o x86.Immediate.binexp)
+                                 {oper = x86.Immediate.Addition,
+                                  exp1 = x86.Immediate.label x86MLton.gcState_label,
+                                  exp2 = x86.Immediate.const_int 
+                                         (Bytes.toInt 
+                                          (Machine.Runtime.GCField.offset
+                                           Machine.Runtime.GCField.Frontier))},
+                          base = NONE, index = NONE, scale = NONE},
+                   dst = x86.Operand.register frontierReg,
+                   size = x86.Size.LONG},
+                  x86.Assembly.instruction_jmp
+                  {target = x86.Operand.register x86.Register.eax,
+                   absolute = true},
+                  x86.Assembly.pseudoop_p2align 
+                  (x86.Immediate.const_int 4, NONE, NONE),
+                  x86.Assembly.pseudoop_global returnToC,
+                  x86.Assembly.label returnToC,
+                  x86.Assembly.instruction_mov
+                  {src = (x86.Operand.address o x86.Address.T)
+                         {disp = SOME (x86.Immediate.label x86MLton.c_stackP),
+                          base = NONE, index = NONE, scale = NONE},
+                   dst = x86.Operand.register x86.Register.esp,
+                   size = x86.Size.LONG},
+                  x86.Assembly.instruction_mov
+                  {src = (x86.Operand.address o x86.Address.T)
+                         {disp = SOME (x86.Immediate.const_int 8),
+                          base = SOME x86.Register.esp,
+                          index = NONE, scale = NONE},
+                   dst = x86.Operand.register x86.Register.ebx,
+                   size = x86.Size.LONG},
+                  x86.Assembly.instruction_mov
+                  {src = x86.Operand.register x86.Register.ebx,
+                   dst = (x86.Operand.address o x86.Address.T)
+                         {disp = SOME (x86.Immediate.label x86MLton.c_stackP),
+                          base = NONE, index = NONE, scale = NONE},
+                   size = x86.Size.LONG},
+                  x86.Assembly.instruction_mov
+                  {src = (x86.Operand.address o x86.Address.T)
+                         {disp = SOME (x86.Immediate.const_int 12),
+                          base = SOME x86.Register.esp,
+                          index = NONE, scale = NONE},
+                   dst = x86.Operand.register x86.Register.esi,
+                   size = x86.Size.LONG},
+                  x86.Assembly.instruction_mov
+                  {src = (x86.Operand.address o x86.Address.T)
+                         {disp = SOME (x86.Immediate.const_int 16),
+                          base = SOME x86.Register.esp,
+                          index = NONE, scale = NONE},
+                   dst = x86.Operand.register x86.Register.edi,
+                   size = x86.Size.LONG},
+                  x86.Assembly.instruction_mov
+                  {src = (x86.Operand.address o x86.Address.T)
+                         {disp = SOME (x86.Immediate.const_int 20),
+                          base = SOME x86.Register.esp,
+                          index = NONE, scale = NONE},
+                   dst = x86.Operand.register x86.Register.ebx,
+                   size = x86.Size.LONG},
+                  x86.Assembly.instruction_mov
+                  {src = (x86.Operand.address o x86.Address.T)
+                         {disp = SOME (x86.Immediate.const_int 24),
+                          base = SOME x86.Register.esp,
+                          index = NONE, scale = NONE},
+                   dst = x86.Operand.register x86.Register.ebp,
+                   size = x86.Size.LONG},
+                  x86.Assembly.instruction_binal
+                  {oper = x86.Instruction.ADD,
+                   src = x86.Operand.immediate_const_int 28,
+                   dst = x86.Operand.register x86.Register.esp,
+                   size = x86.Size.LONG},
+                  x86.Assembly.instruction_ret {src = NONE}
+                  ]
+           in
+              List.foreach
+              (asm,
+               fn asm => (Layout.print(Assembly.layout asm, print);
+                          print "\n"))
+           end
+
         val liveInfo = x86Liveness.LiveInfo.newLiveInfo ()
         val jumpInfo = x86JumpInfo.newJumpInfo ()
 
@@ -194,6 +356,11 @@
               val isMain 
                 = Machine.ChunkLabel.equals(#chunkLabel main, chunkLabel)
 
+              val () 
+                = if isMain
+                     then outputJumpToSML print
+                     else ()
+
               val {chunk}
                 = x86Translate.translateChunk 
                   {chunk = chunk,
@@ -243,7 +410,7 @@
             in
               List.fold
               (validated_assembly,
-               0,
+               if isMain then 30 else 0,
                fn (block, n)
                 => List.fold
                    (block,

Modified: mlton/trunk/mlton/codegen/x86-codegen/x86-mlton-basic.sig
===================================================================
--- mlton/trunk/mlton/codegen/x86-codegen/x86-mlton-basic.sig	2006-10-05 01:37:54 UTC (rev 4717)
+++ mlton/trunk/mlton/codegen/x86-codegen/x86-mlton-basic.sig	2006-10-05 16:41:15 UTC (rev 4718)
@@ -78,6 +78,7 @@
       end
 
     (* CStack locations *)
+    val c_stackP : x86.Label.t
     val c_stackPContents : x86.MemLoc.t
     val c_stackPContentsOperand : x86.Operand.t
     val c_stackPDerefOperand : x86.Operand.t




More information about the MLton-commit mailing list