<html>
<head>
<style><!--
.hmmessage P
{
margin:0px;
padding:0px
}
body.hmmessage
{
font-size: 12pt;
font-family:Calibri
}
--></style></head>
<body class='hmmessage'><div dir='ltr'><div><font face="Calibri, sans-serif">latest debugging/exploration...</font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif">RTLinker.m3 has some indirect call (function call through a pointer).</font></div><div><font face="Calibri, sans-serif">Here are two of them:</font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif">PROCEDURE FixImports (m: RT0.ModulePtr) =</font></div><div><font face="Calibri, sans-serif">  VAR imp: RT0.ImportPtr;</font></div><div><font face="Calibri, sans-serif">  BEGIN</font></div><div><font face="Calibri, sans-serif">    IF (m = NIL) THEN RETURN; END;</font></div><div><font face="Calibri, sans-serif">    TraceModule("FixImports: ", m);</font></div><div><font face="Calibri, sans-serif">    imp := m.imports;</font></div><div><font face="Calibri, sans-serif">    WHILE (imp # NIL) DO</font></div><div><font face="Calibri, sans-serif">      IF (imp.import = NIL) THEN  imp.import := imp.binder (0);  END; (* line 83 *)</font></div><div><font face="Calibri, sans-serif">      imp := imp.next;</font></div><div><font face="Calibri, sans-serif">    END;</font></div><div><font face="Calibri, sans-serif">  END FixImports;</font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif">PROCEDURE AddUnit (b: RT0.Binder) =</font></div><div><font face="Calibri, sans-serif">  VAR m: RT0.ModulePtr;</font></div><div><font face="Calibri, sans-serif">  BEGIN</font></div><div><font face="Calibri, sans-serif">    IF (b = NIL) THEN RETURN END;</font></div><div><font face="Calibri, sans-serif">    m := b(0);  (* line 122 *)</font></div><div><font face="Calibri, sans-serif">    IF (m = NIL) THEN RETURN END;</font></div><div><font face="Calibri, sans-serif">    AddUnitI(m);</font></div><div><font face="Calibri, sans-serif">  END AddUnit;</font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif">m3front sometimes "knows" that an indirect call cannot be to a closure,</font></div><div><font face="Calibri, sans-serif">so sometimes it does "static link stuff", sometimes not, UserProc.m3:</font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif">    ELSIF CouldBeClosure (proc) THEN</font></div><div><font face="Calibri, sans-serif">      ce.tmp := GenClosureCall (p_temp, cg_result, p_type, callConv);</font></div><div><font face="Calibri, sans-serif">      CG.Free (p_temp);</font></div><div><font face="Calibri, sans-serif">    ELSE</font></div><div><font face="Calibri, sans-serif">      CG.Push (p_temp);</font></div><div><font face="Calibri, sans-serif">      CG.Gen_Call_indirect (cg_result, callConv);</font></div><div><font face="Calibri, sans-serif">      ce.tmp := Marker.EmitExceptionTest (p_type, need_value := TRUE);</font></div><div><font face="Calibri, sans-serif">      CG.Free (p_temp);</font></div><div><font face="Calibri, sans-serif">    END;</font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif">PROCEDURE GenClosureCall (p_temp: CG.Val;  result: CG.Type;</font></div><div><font face="Calibri, sans-serif">                          sig: Type.T;  cc: CG.CallingConvention): CG.Val =</font></div><div><font face="Calibri, sans-serif">  VAR skip := CG.Next_label ();</font></div><div><font face="Calibri, sans-serif">  BEGIN</font></div><div><font face="Calibri, sans-serif">    CG.If_closure (p_temp, CG.No_label, skip, CG.Maybe);</font></div><div><font face="Calibri, sans-serif">    CG.Push (p_temp);</font></div><div><font face="Calibri, sans-serif">    CG.Closure_frame ();</font></div><div><font face="Calibri, sans-serif">    CG.Pop_static_link ();   (* *** *)</font></div><div><font face="Calibri, sans-serif">    CG.Push (p_temp);</font></div><div><font face="Calibri, sans-serif">    CG.Closure_proc ();</font></div><div><font face="Calibri, sans-serif">    CG.Store_temp (p_temp);</font></div><div><font face="Calibri, sans-serif">    CG.Set_label (skip);</font></div><div><font face="Calibri, sans-serif">    CG.Push (p_temp);</font></div><div><font face="Calibri, sans-serif">    CG.Gen_Call_indirect (result, cc);</font></div><div><font face="Calibri, sans-serif">    RETURN Marker.EmitExceptionTest (sig, need_value := TRUE);</font></div><div><font face="Calibri, sans-serif">  END GenClosureCall;</font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif">From the two examples and guessing at what the code means, I guess</font></div><div><font face="Calibri, sans-serif">we can't "store closures", like in globals or record fields.</font></div><div><font face="Calibri, sans-serif">They can be parameters and locals.</font></div><div><font face="Calibri, sans-serif">And that is how the compiler knows some things can't be closures.</font></div><div><font face="Calibri, sans-serif">?</font></div><div><font face="Calibri, sans-serif"> </font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif">Aside:</font></div><div><font face="Calibri, sans-serif">The backends are relatively untyped.</font></div><div><font face="Calibri, sans-serif">There is a lot of type information available, but isn't really used.</font></div><div><font face="Calibri, sans-serif">"Following that idea.." whenever my C backend calls through a function pointer,</font></div><div><font face="Calibri, sans-serif">it casts to a function pointer that can accept any parameters:</font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif">#ifdef __cplusplus</font></div><div><font face="Calibri, sans-serif">#define M3_DOTDOTDOT ...</font></div><div><font face="Calibri, sans-serif">#else</font></div><div><font face="Calibri, sans-serif">#define M3_DOTDOTDOT</font></div><div><font face="Calibri, sans-serif">#endif</font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif">(recall that in C void Foo(void) is a function accepts no parameters, but void Foo()</font></div><div><font face="Calibri, sans-serif">is a function that accepts anything; if you do use "..." in C, gcc complains about the</font></div><div><font face="Calibri, sans-serif">lack of any preceding parameters.)</font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif"> (((*)(M3_DOTDOTDOT))function_pointer)(parameters any number of them) </font></div><div><font face="Calibri, sans-serif"> </font></div><div><font face="Calibri, sans-serif"> </font></div><div><font face="Calibri, sans-serif">so, now, let's look at those indirect calls in the generated C (slightly simplified):</font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif">This first one can't be a closure:</font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif"> /* line 83 "../src/runtime/common/RTLinker.m3" */ </font></div><div><font face="Calibri, sans-serif">(*(volatile ADDRESS*)&L_7)=(ADDRESS)(((ADDRESS)(*(volatile ADDRESS*)(4+(ADDRESS)*(volatile ADDRESS*)&imp))));</font></div><div><font face="Calibri, sans-serif"> /* start_call_indirect */ </font></div><div><font face="Calibri, sans-serif">if(!(*(volatile ADDRESS*)&L_7))</font></div><div><font face="Calibri, sans-serif">M_RTLinker_CRASH(2660);</font></div><div><font face="Calibri, sans-serif"> /* call_indirect */ </font></div><div><font face="Calibri, sans-serif"> /* declare_temp => declare_local */ </font></div><div><font face="Calibri, sans-serif"> /* declare_local ADDRESS L_10 */ </font></div><div><font face="Calibri, sans-serif">{</font></div><div><font face="Calibri, sans-serif">ADDRESS L_9 M3_INIT;</font></div><div><font face="Calibri, sans-serif"> /* store */ </font></div><div><font face="Calibri, sans-serif">(*(volatile ADDRESS*)&L_9)=(ADDRESS)(((ADDRESS)(((ADDRESS (__stdcall*)(M3_DOTDOTDOT))*(volatile ADDRESS*)&L_7)(((INT32)(((INT32)M3_INT32(0))))))));</font></div><div><font face="Calibri, sans-serif"> /* line 83 "../src/runtime/common/RTLinker.m3" */  /* load */ </font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif">and this one can be, you can see the telltale check for -1, the closure marker:</font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif"> /* line 122 "../src/runtime/common/RTLinker.m3" */ </font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif">if((((INT32)(*(volatile INT32*)*(volatile ADDRESS*)&L_13)))!=(((INT32)(((INT32)M3_INT32(-1))))))goto L12;</font></div><div><font face="Calibri, sans-serif"> /* set_label */ </font></div><div><font face="Calibri, sans-serif">L13:;</font></div><div><font face="Calibri, sans-serif"> /* load */ </font></div><div><font face="Calibri, sans-serif"> /* load_indirect */ </font></div><div><font face="Calibri, sans-serif"> /* declare_temp => declare_local */ </font></div><div><font face="Calibri, sans-serif"> /* declare_local ADDRESS L_16 */ </font></div><div><font face="Calibri, sans-serif">{</font></div><div><font face="Calibri, sans-serif">ADDRESS L_15 M3_INIT;</font></div><div><font face="Calibri, sans-serif"> /* pop_static_link */ </font></div><div><font face="Calibri, sans-serif"> /* store */ </font></div><div><font face="Calibri, sans-serif">(*(volatile ADDRESS*)&L_15)=(ADDRESS)(((ADDRESS)(*(volatile ADDRESS*)(8+(ADDRESS)*(volatile ADDRESS*)&L_13))));</font></div><div><font face="Calibri, sans-serif"> /* load */ </font></div><div><font face="Calibri, sans-serif"> /* load_indirect */ </font></div><div><font face="Calibri, sans-serif"> /* store */ </font></div><div><font face="Calibri, sans-serif">(*(volatile ADDRESS*)&L_13)=(ADDRESS)(((ADDRESS)(*(volatile ADDRESS*)(4+(ADDRESS)*(volatile ADDRESS*)&L_13))));</font></div><div><font face="Calibri, sans-serif"> /* line 122 "../src/runtime/common/RTLinker.m3" */  /* set_label */ </font></div><div><font face="Calibri, sans-serif">L12:;</font></div><div><font face="Calibri, sans-serif"> /* load */ </font></div><div><font face="Calibri, sans-serif"> /* check_nil */ </font></div><div><font face="Calibri, sans-serif">if(!(*(volatile ADDRESS*)&L_13))</font></div><div><font face="Calibri, sans-serif">M_RTLinker_CRASH(3908);</font></div><div><font face="Calibri, sans-serif"> /* call_indirect */ </font></div><div><font face="Calibri, sans-serif"> /* free_temp */ </font></div><div><font face="Calibri, sans-serif"> /* declare_temp => declare_local */ </font></div><div><font face="Calibri, sans-serif"> /* declare_local ADDRESS L_18 */ </font></div><div><font face="Calibri, sans-serif">{</font></div><div><font face="Calibri, sans-serif">ADDRESS L_17 M3_INIT;</font></div><div><font face="Calibri, sans-serif"> /* store */ </font></div><div><font face="Calibri, sans-serif">(*(volatile ADDRESS*)&L_17)=(ADDRESS)(((ADDRESS)(((ADDRESS (__stdcall*)(M3_DOTDOTDOT))*(volatile ADDRESS*)&L_13)(L_15,((INT32)(((INT32)M3_INT32(0))))))));</font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif">These are actually both calls to "binders", which take one parameter, integer "mode".</font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif">They are both via pointers.</font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif">But the compiler thinks the second one might be a closure.</font></div><div><font face="Calibri, sans-serif">So we get pop_static_link. </font></div><div><font face="Calibri, sans-serif">Following the pattern of M3x86.m3, I therefore pass the static link, unconditionally.</font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif">This is not right!</font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif">For now I'm going to try putting the static link LAST in parameter lists, instead of first.</font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif">I expect that will work.</font></div><div><font face="Calibri, sans-serif">Thanks to printf! :)</font></div><div><font face="Calibri, sans-serif">(on all but one implementation I know of, printf("", 1, 2, 3) is safe and predictable -- you can pass any number of extra parameters to a function and they will be ignored; the stack will not become imbalanced. Anyone with a broad knowledge of calling conventions confirm?)</font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif">The right fix is to use more type information, possibly that which I'm already given.</font></div><div><font face="Calibri, sans-serif">That is going to require multiple passes and a somewhat more sophisticated in-memory</font></div><div><font face="Calibri, sans-serif">state. Currently I have just a bunch of strings, occasionally an array of strings.</font></div><div><font face="Calibri, sans-serif">Not all the data is recieved is received in an ideal order.</font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif">i.e. This should all work, pretty well, but it kind of needs a substantial "rewrite".</font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif"><br></font></div><div><font face="Calibri, sans-serif"> - Jay</font></div><br>                                       </div></body>
</html>