<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>Here are my changes for "alloca(sizeof(jmp_buf))".</div><div><br></div><div><br></div><div>NOTE: I updated 3 of the 4 backends, and tested one of them so far.</div><div>I can test the other two.</div><div><br></div><div><br></div><div>NOTE: The update procedure is the same as usual, and very important,</div><div> given the change to M3RT/m3-libs/m3core/src/runtime/ex_frame/RTExFrame.m3.</div><div> The compiler output is closedly tied to m3core.</div><div><br></div><div><br></div><div><br></div><div>NOTE: This uses alloca even for the C backend. I expect to do better later.</div><div><br></div><div><br></div><div>NOTE: The real value here is the deletion of all the target-dependent lines</div><div>in m3-sys/m3middle/src/Target.m3.</div><div><br></div><div><br></div><div>diff --git a/m3-libs/m3core/src/C/Common/Csetjmp.i3 b/m3-libs/m3core/src/C/Common/Csetjmp.i3</div><div>index bd75beb..df2f139 100755</div><div>--- a/m3-libs/m3core/src/C/Common/Csetjmp.i3</div><div>+++ b/m3-libs/m3core/src/C/Common/Csetjmp.i3</div><div>@@ -5,11 +5,22 @@</div><div> UNSAFE INTERFACE Csetjmp;</div><div> FROM Ctypes IMPORT int;</div><div> </div><div>-(* jmp_buf is allocated with alloca(Csetjmp__Jumpbuf_size)</div><div>+(* TODO? Move this to C?</div><div>+</div><div> "u" in "ulongjmp" is probably for "underscore".</div><div> This variant of longjmp never restores the signal mask.</div><div>+ Because we believe we never change it?</div><div>+ And restoring it is less efficient? (Requires possible kernel</div><div>+ interaction?)</div><div>+</div><div>+ If the platform only has "regular" longjmp and no signal mask,</div><div>+ e.g. Win32, then this is resolved to that.</div><div>+ </div><div>+ This function does not return in the usual sense.</div><div>+ This is used to raise an exception.</div><div>+ This is subject to be removed, either by using C, or "libunwind", or</div><div>+ Win32 exceptions, or C++ exceptions.</div><div> *)</div><div>-<*EXTERNAL "Csetjmp__Jumpbuf_size" *> VAR Jumpbuf_size: INTEGER;</div><div> <*EXTERNAL "Csetjmp__ulongjmp" *> PROCEDURE ulongjmp (env: ADDRESS; val: int);</div><div> </div><div> END Csetjmp.</div><div>diff --git a/m3-libs/m3core/src/m3core.h b/m3-libs/m3core/src/m3core.h</div><div>index 37a9862..4be9ac3 100644</div><div>--- a/m3-libs/m3core/src/m3core.h</div><div>+++ b/m3-libs/m3core/src/m3core.h</div><div>@@ -358,7 +358,9 @@ extern "C" {</div><div> /* WORD_T/INTEGER are always exactly the same size as a pointer.</div><div> * VMS sometimes has 32bit size_t/ptrdiff_t but 64bit pointers.</div><div> */</div><div>-#if defined(_WIN64) || __INITIAL_POINTER_SIZE == 64 || defined(__LP64__) || defined(_LP64)</div><div>+/* commented out is correct, but so is the #else */</div><div>+/*#if defined(_WIN64) || __INITIAL_POINTER_SIZE == 64 || defined(__LP64__) || defined(_LP64)*/</div><div>+#if __INITIAL_POINTER_SIZE == 64</div><div> typedef INT64 INTEGER;</div><div> typedef UINT64 WORD_T;</div><div> #else</div><div>diff --git a/m3-libs/m3core/src/runtime/ex_frame/RTExFrame.m3 b/m3-libs/m3core/src/runtime/ex_frame/RTExFrame.m3</div><div>index 6ec33fc..423a835 100644</div><div>--- a/m3-libs/m3core/src/runtime/ex_frame/RTExFrame.m3</div><div>+++ b/m3-libs/m3core/src/runtime/ex_frame/RTExFrame.m3</div><div>@@ -36,7 +36,7 @@ TYPE (* Except, ExceptElse, Finally *)</div><div> class : INTEGER; (* ORD(ScopeKind) *)</div><div> handles : ExceptionList; (* NIL-terminated list of exceptions handled *)</div><div> info : RT0.RaiseActivation; (* current exception being dispatched *)</div><div>- jmpbuf : ARRAY [0..16_FFFF] OF LONGREAL; (* gigantic, size is not used *)</div><div>+ jmpbuf : ADDRESS; (* allocated with alloca *)</div><div> END;</div><div> </div><div> TYPE (* FinallyProc *)</div><div>@@ -172,7 +172,7 @@ PROCEDURE InvokeHandler (f: Frame; READONLY a: RT0.RaiseActivation) RAISES ANY</div><div> END;</div><div> RTThread.SetCurrentHandlers (f.next); (* cut to the new handler *)</div><div> p.info := a; (* copy the exception to the new frame *)</div><div>- Csetjmp.ulongjmp (ADR(p.jmpbuf), 1); (* and jump... *)</div><div>+ Csetjmp.ulongjmp (p.jmpbuf, 1); (* and jump... *)</div><div> RAISE OUCH;</div><div> END InvokeHandler;</div><div> </div><div>diff --git a/m3-libs/m3core/src/unix/Common/Uconstants.c b/m3-libs/m3core/src/unix/Common/Uconstants.c</div><div>index 99b1adf..84095c1 100644</div><div>--- a/m3-libs/m3core/src/unix/Common/Uconstants.c</div><div>+++ b/m3-libs/m3core/src/unix/Common/Uconstants.c</div><div>@@ -46,7 +46,7 @@ typedef int CheckMax[248 - sizeof(CheckMax_t)];</div><div> #include "UerrorX.h"</div><div> </div><div> /* This needs to be aligned to 16, at least for Win32. */</div><div>-EXTERN_CONST INTEGER Csetjmp__Jumpbuf_size = ((sizeof(jmp_buf) + 15) & ~15);</div><div>+EXTERN_CONST INTEGER m3_jmpbuf_size = ((sizeof(jmp_buf) + 15) & ~15);</div><div> </div><div> #ifndef _WIN32</div><div> </div><div>diff --git a/m3-sys/cminstall/src/config-no-install/Darwin.common b/m3-sys/cminstall/src/config-no-install/Darwin.common</div><div>index 0bf3e7e..7043383 100644</div><div><span style="font-size: 12pt; "> </span><span style="font-size: 12pt; ">diff --git a/m3-sys/m3back/src/M3C.m3 b/m3-sys/m3back/src/M3C.m3</span></div><div>index 82285e9..ab858b0 100644</div><div>--- a/m3-sys/m3back/src/M3C.m3</div><div>+++ b/m3-sys/m3back/src/M3C.m3</div><div>@@ -66,7 +66,7 @@ T = M3CG_DoNothing.T BRANDED "M3C.T" OBJECT</div><div> Err : ErrorHandler := DefaultErrorHandler;</div><div> anonymousCounter := -1;</div><div> c : Wr.T := NIL;</div><div>- debug := 0; (* or 0, 1, 2, 3, 4 *)</div><div>+ debug := 1; (* 1-4 *)</div><div> stack : RefSeq.T := NIL;</div><div> params : TextSeq.T := NIL;</div><div> op_index := 0;</div><div>@@ -80,6 +80,10 @@ T = M3CG_DoNothing.T BRANDED "M3C.T" OBJECT</div><div> RTHooks_Raise_id: M3ID.T := 0;</div><div> RTHooks_ReportFault_id: M3ID.T := 0;</div><div> RTHooks_ReportFault_imported_or_declared := FALSE;</div><div>+ alloca_id : M3ID.T := 0;</div><div>+ setjmp_id : M3ID.T := 0;</div><div>+ u_setjmp_id : M3ID.T := 0;</div><div>+ longjmp_id : M3ID.T := 0;</div><div> </div><div> (* labels *)</div><div> labels_min := FIRST(Label);</div><div>@@ -1679,6 +1683,7 @@ TYPE Proc_t = M3CG.Proc OBJECT</div><div> uplevels := FALSE;</div><div> is_exception_handler := FALSE;</div><div> is_RTHooks_Raise := FALSE;</div><div>+ omit_prototype := FALSE;</div><div> is_RTException_Raise := FALSE;</div><div> no_return := FALSE;</div><div> exit_proc_skipped := 0;</div><div>@@ -1752,23 +1757,45 @@ BEGIN</div><div> END IsNameExceptionHandler;</div><div> </div><div> PROCEDURE Proc_Init(proc: Proc_t; self: T): Proc_t =</div><div>-VAR is_common := (proc.parent = NIL</div><div>- AND (proc.exported = TRUE OR proc.imported = TRUE)</div><div>- AND proc.level = 0</div><div>- AND proc.return_type = CGType.Void);</div><div>- is_RTHooks_ReportFault := (is_common</div><div>- AND proc.name = self.RTHooks_ReportFault_id</div><div>- AND proc.parameter_count = 2);</div><div>- is_RTHooks_AssertFailed := (is_common</div><div>- AND proc.name = self.RTHooks_AssertFailed_id</div><div>- AND proc.parameter_count = 3);</div><div>-BEGIN</div><div>- proc.is_RTHooks_Raise := (is_common</div><div>- AND proc.name = self.RTHooks_Raise_id</div><div>- AND proc.parameter_count = 4);</div><div>- proc.is_RTException_Raise := (is_common</div><div>- AND proc.name = self.RTException_Raise_id</div><div>- AND proc.parameter_count = 1);</div><div>+VAR name := proc.name;</div><div>+ parameter_count := proc.parameter_count;</div><div>+ is_common := proc.parent = NIL</div><div>+ AND (proc.exported = TRUE OR proc.imported = TRUE)</div><div>+ AND proc.level = 0;</div><div>+ is_common_void := is_common AND proc.return_type = CGType.Void;</div><div>+ is_RTHooks_ReportFault := is_common_void</div><div>+ AND name = self.RTHooks_ReportFault_id</div><div>+ AND parameter_count = 2;</div><div>+ is_RTHooks_AssertFailed := is_common_void</div><div>+ AND name = self.RTHooks_AssertFailed_id</div><div>+ AND parameter_count = 3;</div><div>+BEGIN</div><div>+ (* Omit a few prototypes that the frontend might have slightly wrong,</div><div>+ e.g. alloca(unsigned int vs. unsigned long vs. unsigned long long)</div><div>+ vs. not a function.</div><div>+ e.g. setjmp(void* ) vs. setjmp(array)</div><div>+ *)</div><div>+ proc.omit_prototype := is_common</div><div>+ AND parameter_count = 1 (* TODO 2 for longjmp *)</div><div>+ AND (name = self.alloca_id</div><div>+ (* TODO</div><div>+ - add CGType.Jmpbuf</div><div>+ - #include <setjmp.h> if there are any</div><div>+ calls to setjmp/_setjmp/longjmp</div><div>+ or instances of CGType.Jmpbuf</div><div>+ - render CGType.Jmpbuf as "jmp_buf"</div><div>+ - omit setjmp/_setjmp/longjmp prototypes</div><div>+ OR name = self.setjmp_id</div><div>+ OR name = self.u_setjmp_id</div><div>+ OR name = self.longjmp_id</div><div>+ *)</div><div>+ );</div><div>+ proc.is_RTHooks_Raise := is_common_void</div><div>+ AND name = self.RTHooks_Raise_id</div><div>+ AND parameter_count = 4;</div><div>+ proc.is_RTException_Raise := is_common_void</div><div>+ AND name = self.RTException_Raise_id</div><div>+ AND parameter_count = 1;</div><div> IF is_RTHooks_ReportFault THEN</div><div> self.RTHooks_ReportFault_imported_or_declared := TRUE;</div><div> END;</div><div>@@ -1777,9 +1804,10 @@ BEGIN</div><div> no_return(self);</div><div> END;</div><div> proc.self := self;</div><div>- proc.name := Proc_FixName(proc.self, proc.name);</div><div>- proc.is_exception_handler := proc.level > 0 AND proc.parameter_count = 1 AND IsNameExceptionHandler(self, NameT(proc.name));</div><div>- proc.parameter_count_without_static_link := proc.parameter_count;</div><div>+ proc.name := Proc_FixName(proc.self, name);</div><div>+ name := proc.name;</div><div>+ proc.is_exception_handler := proc.level > 0 AND parameter_count = 1 AND IsNameExceptionHandler(self, NameT(name));</div><div>+ proc.parameter_count_without_static_link := parameter_count;</div><div> proc.add_static_link := proc.level > 0;</div><div> INC(proc.parameter_count, ORD(proc.add_static_link));</div><div> proc.locals := NEW(RefSeq.T).init();</div><div>@@ -1865,8 +1893,10 @@ CONST Prefix = ARRAY OF TEXT {</div><div> "#pragma warning(disable:4255) /* () change to (void) */",</div><div> "#pragma warning(disable:4668) /* #if of undefined symbol */",</div><div> "#endif",</div><div>-"typedef char* ADDRESS;", (* TODO remove this when we finish strong typing *)</div><div>-"typedef char* STRUCT;", (* TODO remove this when we finish strong typing *)</div><div>+(* TODO ideally these are char* for K&R or ideally absent when strong</div><div>+ typing and setjmp work done *)</div><div>+"typedef char* ADDRESS;",</div><div>+"typedef char* STRUCT;",</div><div> "typedef signed char INT8;",</div><div> "typedef unsigned char UINT8;",</div><div> "typedef short INT16;",</div><div>@@ -1907,6 +1937,8 @@ CONST Prefix = ARRAY OF TEXT {</div><div> "#include <stddef.h>", (* try to remove this, it is slow -- need size_t *)</div><div> "#endif",</div><div> </div><div>+(* "#include <setjmp.h>", TODO do not always #include *)</div><div>+</div><div> "/* http://c.knowcoding.com/view/23699-portable-alloca.html */",</div><div> "/* Find a good version of alloca. */",</div><div> "#ifndef alloca",</div><div>@@ -1946,7 +1978,7 @@ CONST Prefix = ARRAY OF TEXT {</div><div> "#define STRUCT1(n) typedef struct { volatile char a[n]; } STRUCT(n);", (* TODO prune if not used *)</div><div> "#define STRUCT2(n) typedef struct { volatile short a[n/2]; } STRUCT(n);", (* TODO prune if not used *)</div><div> "#define STRUCT4(n) typedef struct { volatile int a[n/4]; } STRUCT(n);", (* TODO prune if not used *)</div><div>-"#define STRUCT8(n) typedef struct { volatile double a[n/8]; } STRUCT(n);", (* TODO prune if not used *)</div><div>+"#define STRUCT8(n) typedef struct { volatile UINT64 a[n/8]; } STRUCT(n);", (* TODO prune if not used *)</div><div> "#ifdef __cplusplus",</div><div> "#define DOTDOTDOT ...",</div><div> "#else",</div><div>@@ -2285,6 +2317,10 @@ BEGIN</div><div> self.comment("M3_TARGET = ", Target.System_name);</div><div> self.comment("M3_WORDSIZE = ", IntToDec(Target.Word.size));</div><div> self.static_link_id := M3ID.Add("_static_link");</div><div>+ self.alloca_id := M3ID.Add("alloca");</div><div>+ self.setjmp_id := M3ID.Add("setjmp");</div><div>+ self.u_setjmp_id := M3ID.Add("_setjmp"); (* "u" is for underscore *)</div><div>+ self.longjmp_id := M3ID.Add("longjmp");</div><div> self.RTHooks_ReportFault_id := M3ID.Add("RTHooks__ReportFault");</div><div> self.RTHooks_Raise_id := M3ID.Add("RTHooks__Raise");</div><div> self.RTException_Raise_id := M3ID.Add("RTException__Raise");</div><div>@@ -3555,6 +3591,7 @@ BEGIN</div><div> HelperFunctions_helper_with_type_and_array(self, op, type, types, ARRAY OF TEXT{first});</div><div> END HelperFunctions_helper_with_type;</div><div> </div><div>+(* TODO give up and #include <string.h>? *)</div><div> PROCEDURE HelperFunctions_memset(self: HelperFunctions_t) =</div><div> CONST text = "void* __cdecl memset(void*, int, size_t); /* string.h */";</div><div> BEGIN</div><div>@@ -4270,6 +4307,9 @@ VAR params := proc.params;</div><div> define_kr := NOT ansi AND kind = FunctionPrototype_t.Define;</div><div> kr_part2 := "";</div><div> BEGIN</div><div>+ IF proc.omit_prototype THEN</div><div>+ RETURN "";</div><div>+ END;</div><div> IF NUMBER (params^) = 0 THEN</div><div> text := text & "(void)";</div><div> ELSIF NOT ansi AND NOT define_kr THEN</div><div>diff --git a/m3-sys/m3back/src/M3x86.m3 b/m3-sys/m3back/src/M3x86.m3</div><div>index 206f9fb..2fff809 100644</div><div>--- a/m3-sys/m3back/src/M3x86.m3</div><div>+++ b/m3-sys/m3back/src/M3x86.m3</div><div>@@ -3283,7 +3283,7 @@ CONST</div><div> BP { "m3_rotate_right64",3, Type.Word64, Target.STDCALL },</div><div> BP { "m3_rotate64", 3, Type.Word64, Target.STDCALL },</div><div> </div><div>- BP { "m3_alloca", 0, Type.Addr, Target.CDECL, "__chkstk", EAX }</div><div>+ BP { "alloca", 0, Type.Addr, Target.CDECL, "__chkstk", EAX }</div><div> };</div><div> </div><div> PROCEDURE start_int_proc (u: U; b: Builtin) =</div><div>diff --git a/m3-sys/m3cc/gcc/gcc/m3cg/parse.c b/m3-sys/m3cc/gcc/gcc/m3cg/parse.c</div><div>index d965c8a..fdbbdf4 100644</div><div>--- a/m3-sys/m3cc/gcc/gcc/m3cg/parse.c</div><div>+++ b/m3-sys/m3cc/gcc/gcc/m3cg/parse.c</div><div>@@ -643,7 +643,7 @@ static GTY (()) tree t_int;</div><div> #define t_void void_type_node</div><div> static GTY (()) tree t_set;</div><div> </div><div>-static tree m3_alloca;</div><div>+static tree alloca_tree;</div><div> </div><div> static const struct { UINT32 type_id; tree* t; } builtin_uids[] = {</div><div> { UID_INTEGER, &t_int },</div><div>@@ -1914,7 +1914,7 @@ m3_init_decl_processing (void)</div><div> bits_per_integer_tree = build_int_cst (t_word, BITS_PER_INTEGER);</div><div> bytes_per_integer_tree = build_int_cst (t_word, BITS_PER_INTEGER / BITS_PER_UNIT);</div><div> tree stdcall = get_identifier_with_length (CONSTANT_STRING_AND_LENGTH ("stdcall"));</div><div>- m3_alloca = get_identifier_with_length (CONSTANT_STRING_AND_LENGTH ("m3_alloca"));</div><div>+ alloca_tree = get_identifier_with_length (CONSTANT_STRING_AND_LENGTH ("alloca"));</div><div> stdcall_list = build_tree_list (stdcall, NULL);</div><div> t_set = m3_build_pointer_type (t_word);</div><div> </div><div>@@ -3076,7 +3076,7 @@ fix_name (PCSTR name, size_t length, UINT32 type_id)</div><div> }</div><div> else if (type_id == NO_UID)</div><div> {</div><div>- buf = (PSTR)alloca (sizet_add(length, 1));</div><div>+ buf = (PSTR)alloca (sizet_add (length, 1));</div><div> buf[0] = 'M';</div><div> memcpy (&buf[1], name, length);</div><div> length += 1;</div><div>@@ -3153,7 +3153,8 @@ m3_pop_param (tree type)</div><div> static tree</div><div> m3_convert_function_to_builtin (tree p)</div><div> {</div><div>- if (DECL_NAME (p) == m3_alloca)</div><div>+ tree name = DECL_NAME (p);</div><div>+ if (name == alloca_tree)</div><div> p = builtin_decl_explicit (BUILT_IN_ALLOCA);</div><div> return p;</div><div> }</div><div>diff --git a/m3-sys/m3front/src/misc/M3.i3 b/m3-sys/m3front/src/misc/M3.i3</div><div>index ec7f972..4a3793e 100644</div><div>--- a/m3-sys/m3front/src/misc/M3.i3</div><div>+++ b/m3-sys/m3front/src/misc/M3.i3</div><div>@@ -11,7 +11,7 @@</div><div> </div><div> INTERFACE M3;</div><div> </div><div>-IMPORT M3ID, M3Buf;</div><div>+IMPORT M3ID, M3Buf, Jmpbufs;</div><div> </div><div> TYPE</div><div> Flag = BITS 1 FOR BOOLEAN;</div><div>@@ -33,6 +33,7 @@ TYPE</div><div> ExSet <: Node; (* == ESet.T *)</div><div> ExSetList <: REFANY; (* == list of ExSet *)</div><div> EqAssumption <: ADDRESS; (* == Type.Assumption *)</div><div>+ Procedure <: Value; (* == Procedure.T *)</div><div> </div><div> (*--------------------------------------------------------- type checking ---*)</div><div> </div><div>@@ -41,13 +42,15 @@ TYPE (* the "global state" that is passed around during type checking *)</div><div> raises_others : BOOLEAN;</div><div> ok_to_raise : ExSetList;</div><div> no_error : ExSetList;</div><div>+ jmpbufs := Jmpbufs.CheckState { };</div><div> END;</div><div> </div><div> CONST</div><div> OuterCheckState = CheckState {</div><div> raises_others := FALSE,</div><div> ok_to_raise := NIL,</div><div>- no_error := NIL</div><div>+ no_error := NIL,</div><div>+ jmpbufs := Jmpbufs.CheckState { }</div><div> };</div><div> </div><div> (*-------------------------------------------------------- fingerprinting ---*)</div><div>diff --git a/m3-sys/m3front/src/misc/Marker.i3 b/m3-sys/m3front/src/misc/Marker.i3</div><div>index db880a0..8d8f044 100644</div><div>--- a/m3-sys/m3front/src/misc/Marker.i3</div><div>+++ b/m3-sys/m3front/src/misc/Marker.i3</div><div>@@ -64,8 +64,9 @@ PROCEDURE PopFrame (frame: CG.Var);</div><div> PROCEDURE SetLock (acquire: BOOLEAN; var: CG.Var; offset: INTEGER);</div><div> (* generate the call to acquire or release a mutex *)</div><div> </div><div>-PROCEDURE CaptureState (frame: CG.Var; handler: CG.Label);</div><div>-(* call 'setjmp' on 'frame's jmpbuf and branch to 'handler' on re-returns. *)</div><div>+PROCEDURE CaptureState (frame: CG.Var; jmpbuf: CG.Var; handler: CG.Label);</div><div>+(* frame.jmpbuf = jmpbuf</div><div>+ if (setjmp(jmpbuf)) goto handler *)</div><div> </div><div> PROCEDURE Reset ();</div><div> </div><div>diff --git a/m3-sys/m3front/src/misc/Marker.m3 b/m3-sys/m3front/src/misc/Marker.m3</div><div>index 6512fbb..9421b7c 100644</div><div>--- a/m3-sys/m3front/src/misc/Marker.m3</div><div>+++ b/m3-sys/m3front/src/misc/Marker.m3</div><div>@@ -53,9 +53,6 @@ VAR</div><div> all_frames : FramePtr := NIL;</div><div> n_frames : INTEGER := 0;</div><div> save_depth : INTEGER := 0;</div><div>- setjmp : CG.Proc := NIL;</div><div>- alloca : CG.Proc := NIL;</div><div>- Jumpbuf_size : CG.Var := NIL;</div><div> tos : INTEGER := 0;</div><div> stack : ARRAY [0..50] OF Frame;</div><div> </div><div>@@ -231,68 +228,13 @@ PROCEDURE CallFinallyHandler (info: CG.Var;</div><div> END;</div><div> END CallFinallyHandler;</div><div> </div><div>-PROCEDURE CaptureState (frame: CG.Var; handler: CG.Label) =</div><div>- CONST Alloca_jmpbuf = FALSE;</div><div>- VAR new: BOOLEAN;</div><div>- label_already_allocated: CG.Label;</div><div>- BEGIN</div><div>- (* int setjmp(void* ); *)</div><div>- IF setjmp = NIL THEN</div><div>- setjmp := CG.Import_procedure (M3ID.Add (Target.Setjmp), 1,</div><div>- Target.Integer.cg_type,</div><div>- Target.DefaultCall, new);</div><div>- IF (new) THEN</div><div>- EVAL CG.Declare_param (M3ID.Add ("jmpbuf"), Target.Address.size,</div><div>- Target.Address.align, CG.Type.Addr, 0,</div><div>- in_memory := FALSE, up_level := FALSE,</div><div>- f := CG.Never);</div><div>- END;</div><div>- END;</div><div>- </div><div>- IF Alloca_jmpbuf THEN</div><div>- label_already_allocated := CG.Next_label ();</div><div>-</div><div>- (* void* _alloca(size_t); *)</div><div>- IF alloca = NIL THEN</div><div>- alloca := CG.Import_procedure (M3ID.Add ("m3_alloca"), 1, CG.Type.Addr,</div><div>- Target.DefaultCall, new);</div><div>- IF new THEN</div><div>- EVAL CG.Declare_param (M3ID.NoID, Target.Word.size, Target.Word.align,</div><div>- Target.Word.cg_type, 0, in_memory := FALSE,</div><div>- up_level := FALSE, f := CG.Never);</div><div>- END;</div><div>- END;</div><div>- (* extern /*const*/ size_t Csetjmp__Jumpbuf_size/* = sizeof(jmp_buf)*/; *)</div><div>- IF Jumpbuf_size = NIL THEN</div><div>- Jumpbuf_size := CG.Import_global (M3ID.Add ("Csetjmp__Jumpbuf_size"),</div><div>- Target.Word.size, Target.Word.align,</div><div>- Target.Word.cg_type, 0);</div><div>- END;</div><div>- </div><div>- (* if (!frame.jmpbuf)</div><div>- frame.jmpbuf = alloca(Csetjmp__Jumpbuf_size);</div><div>- *)</div><div>- CG.Load_addr (frame, M3RT.EF1_jmpbuf);</div><div>- CG.Load_nil ();</div><div>- CG.If_compare (Target.Address.cg_type, CG.Cmp.NE, label_already_allocated, CG.Likely);</div><div>-</div><div>- CG.Start_call_direct (alloca, 0, Target.Address.cg_type);</div><div>- CG.Load_int (Target.Word.cg_type, Jumpbuf_size);</div><div>- CG.Pop_param (Target.Word.cg_type);</div><div>- CG.Call_direct (alloca, Target.Address.cg_type);</div><div>- CG.Check_nil (CG.RuntimeError.BadMemoryReference);</div><div>- CG.Store_addr (frame, M3RT.EF1_jmpbuf);</div><div>-</div><div>- CG.Set_label (label_already_allocated);</div><div>- END;</div><div>-</div><div>- (* setjmp(frame.jmpbuf) or setjmp(&frame.jmpbuf) *)</div><div>+PROCEDURE CaptureState (frame: CG.Var; jmpbuf: CG.Var; handler: CG.Label) =</div><div>+ VAR setjmp := Module.GetSetjmp (Module.Current ());</div><div>+ BEGIN</div><div>+ CG.Load_addr (jmpbuf);</div><div>+ CG.Store_addr (frame, M3RT.EF1_jmpbuf);</div><div> CG.Start_call_direct (setjmp, 0, Target.Integer.cg_type);</div><div>- IF Alloca_jmpbuf THEN</div><div>- CG.Load_addr (frame, M3RT.EF1_jmpbuf);</div><div>- ELSE</div><div>- CG.Load_addr_of (frame, M3RT.EF1_jmpbuf, 128);</div><div>- END;</div><div>+ CG.Load_addr (jmpbuf);</div><div> CG.Pop_param (CG.Type.Addr);</div><div> CG.Call_direct (setjmp, Target.Integer.cg_type);</div><div> CG.If_true (handler, CG.Never);</div><div>@@ -820,9 +762,6 @@ PROCEDURE Reset () =</div><div> all_frames := NIL;</div><div> n_frames := 0;</div><div> save_depth := 0;</div><div>- setjmp := NIL;</div><div>- alloca := NIL;</div><div>- Jumpbuf_size := NIL;</div><div> tos := 0;</div><div> END Reset;</div><div> </div><div>diff --git a/m3-sys/m3front/src/misc/m3makefile b/m3-sys/m3front/src/misc/m3makefile</div><div>index 721cc27..7d5fba3 100644</div><div>--- a/m3-sys/m3front/src/misc/m3makefile</div><div>+++ b/m3-sys/m3front/src/misc/m3makefile</div><div>@@ -16,6 +16,7 @@ module ("M3WString")</div><div> module ("Token")</div><div> module ("Error")</div><div> module ("Host")</div><div>+module ("Jmpbufs")</div><div> module ("Marker")</div><div> module ("Scanner")</div><div> module ("Scope")</div><div>diff --git a/m3-sys/m3front/src/stmts/TryFinStmt.m3 b/m3-sys/m3front/src/stmts/TryFinStmt.m3</div><div>index 89233c5..e0d9b33 100644</div><div>--- a/m3-sys/m3front/src/stmts/TryFinStmt.m3</div><div>+++ b/m3-sys/m3front/src/stmts/TryFinStmt.m3</div><div>@@ -10,6 +10,7 @@ MODULE TryFinStmt;</div><div> </div><div> IMPORT M3ID, CG, Token, Scanner, Stmt, StmtRep, Marker, Target, Type, Addr;</div><div> IMPORT RunTyme, Procedure, ProcBody, M3RT, Scope, Fmt, Host, TryStmt, Module;</div><div>+IMPORT Jmpbufs;</div><div> FROM Stmt IMPORT Outcome;</div><div> </div><div> TYPE</div><div>@@ -20,6 +21,7 @@ TYPE</div><div> viaProc : BOOLEAN;</div><div> scope : Scope.T;</div><div> handler : HandlerProc;</div><div>+ jmpbufs : Jmpbufs.Try;</div><div> OVERRIDES</div><div> check := Check;</div><div> compile := Compile;</div><div>@@ -30,6 +32,7 @@ TYPE</div><div> HandlerProc = ProcBody.T OBJECT</div><div> self: P;</div><div> activation: CG.Var;</div><div>+ jmpbufs : Jmpbufs.Proc;</div><div> OVERRIDES</div><div> gen_decl := EmitDecl;</div><div> gen_body := EmitBody;</div><div>@@ -66,6 +69,7 @@ PROCEDURE Parse (body: Stmt.T; ): Stmt.T =</div><div> PROCEDURE Check (p: P; VAR cs: Stmt.CheckState) =</div><div> VAR zz: Scope.T; oc: Stmt.Outcomes; name: INTEGER;</div><div> BEGIN</div><div>+ Jmpbufs.CheckTry (cs.jmpbufs, p.jmpbufs);</div><div> Marker.PushFinally (CG.No_label, CG.No_label, NIL);</div><div> Stmt.TypeCheck (p.body, cs);</div><div> Marker.Pop ();</div><div>@@ -89,8 +93,11 @@ PROCEDURE Check (p: P; VAR cs: Stmt.CheckState) =</div><div> next_uid := 0;</div><div> END;</div><div> zz := Scope.Push (p.scope);</div><div>+ p.handler.jmpbufs := Jmpbufs.CheckProcPush (cs.jmpbufs,</div><div>+ M3ID.Add (p.handler.name));</div><div> Scope.TypeCheck (p.scope, cs);</div><div> Stmt.TypeCheck (p.finally, cs);</div><div>+ Jmpbufs.CheckProcPop (cs.jmpbufs, p.handler.jmpbufs);</div><div> Scope.Pop (zz);</div><div> END;</div><div> END;</div><div>@@ -226,6 +233,7 @@ PROCEDURE Compile2 (p: P): Stmt.Outcomes =</div><div> CG.Gen_location (p.forigin);</div><div> IF (Host.inline_nested_procs) THEN</div><div> CG.Begin_procedure (p.handler.cg_proc);</div><div>+ Jmpbufs.CompileProcAllocateJmpbufs (p.handler.jmpbufs);</div><div> xc := Stmt.Compile (p.finally);</div><div> CG.Exit_proc (CG.Type.Void);</div><div> CG.End_procedure (p.handler.cg_proc);</div><div>@@ -272,6 +280,7 @@ PROCEDURE EmitBody (x: HandlerProc) =</div><div> Scanner.offset := p.forigin;</div><div> CG.Gen_location (p.forigin);</div><div> CG.Begin_procedure (x.cg_proc);</div><div>+ Jmpbufs.CompileProcAllocateJmpbufs (x.jmpbufs);</div><div> EVAL Stmt.Compile (p.finally);</div><div> CG.Exit_proc (CG.Type.Void);</div><div> CG.End_procedure (x.cg_proc);</div><div>@@ -302,7 +311,7 @@ PROCEDURE Compile3 (p: P): Stmt.Outcomes =</div><div> l := CG.Next_label (3);</div><div> CG.Set_label (l, barrier := TRUE);</div><div> Marker.PushFrame (frame, M3RT.HandlerClass.Finally);</div><div>- Marker.CaptureState (frame, l+1);</div><div>+ Marker.CaptureState (frame, Jmpbufs.CompileTryGetJmpbuf (p.jmpbufs), l+1);</div><div> </div><div> (* compile the body *)</div><div> Marker.PushFinally (l, l+1, frame);</div><div>diff --git a/m3-sys/m3front/src/stmts/TryStmt.m3 b/m3-sys/m3front/src/stmts/TryStmt.m3</div><div>index 8e7a308..a81e0da 100644</div><div>--- a/m3-sys/m3front/src/stmts/TryStmt.m3</div><div>+++ b/m3-sys/m3front/src/stmts/TryStmt.m3</div><div>@@ -10,7 +10,7 @@ MODULE TryStmt;</div><div> </div><div> IMPORT M3, M3ID, CG, Variable, Scope, Exceptionz, Value, Error, Marker;</div><div> IMPORT Type, Stmt, StmtRep, TryFinStmt, Token;</div><div>-IMPORT Scanner, ESet, Target, M3RT, Tracer;</div><div>+IMPORT Scanner, ESet, Target, M3RT, Tracer, Jmpbufs;</div><div> FROM Scanner IMPORT Match, MatchID, GetToken, Fail, cur;</div><div> </div><div> TYPE</div><div>@@ -22,6 +22,7 @@ TYPE</div><div> hasElse : BOOLEAN;</div><div> elseBody : Stmt.T;</div><div> handled : ESet.T;</div><div>+ jmpbufs : Jmpbufs.Try;</div><div> OVERRIDES</div><div> check := Check;</div><div> compile := Compile;</div><div>@@ -162,6 +163,7 @@ PROCEDURE ReverseHandlers (p: P) =</div><div> PROCEDURE Check (p: P; VAR cs: Stmt.CheckState) =</div><div> VAR h: Handler; handled: ESet.T;</div><div> BEGIN</div><div>+ Jmpbufs.CheckTry (cs.jmpbufs, p.jmpbufs);</div><div> h := p.handles;</div><div> WHILE (h # NIL) DO CheckLabels (h, p.scope, cs); h := h.next; END;</div><div> </div><div>@@ -429,7 +431,7 @@ PROCEDURE Compile2 (p: P): Stmt.Outcomes =</div><div> END;</div><div> </div><div> (* capture the machine state *)</div><div>- Marker.CaptureState (frame, l+1);</div><div>+ Marker.CaptureState (frame, Jmpbufs.CompileTryGetJmpbuf (p.jmpbufs), l+1);</div><div> </div><div> (* compile the body *)</div><div> oc := Stmt.Compile (p.body);</div><div>diff --git a/m3-sys/m3front/src/values/Module.i3 b/m3-sys/m3front/src/values/Module.i3</div><div>index 58fa9bd..3935126 100644</div><div>--- a/m3-sys/m3front/src/values/Module.i3</div><div>+++ b/m3-sys/m3front/src/values/Module.i3</div><div>@@ -72,4 +72,13 @@ PROCEDURE Reset ();</div><div> PROCEDURE MakeCurrent (t: T);</div><div> (* refresh 't' and its imports for the current compilation *)</div><div> </div><div>+(* Exception handling support, using setjmp/longjmp, w/o front/middle-end</div><div>+ knowing jmpbuf size -- use alloca at runtime getting size from</div><div>+ constant initialized in C; these functions are in Module</div><div>+ to accomodate hypothetical multi-threaded m3front,</div><div>+ i.e. instead of having globals initialized on-demand in Jmpbufs. *)</div><div>+PROCEDURE GetAlloca (t: T) : CG.Proc;</div><div>+PROCEDURE GetJmpbufSize (t: T): CG.Var;</div><div>+PROCEDURE GetSetjmp (t: T) : CG.Proc;</div><div>+</div><div> END Module.</div><div>diff --git a/m3-sys/m3front/src/values/Module.m3 b/m3-sys/m3front/src/values/Module.m3</div><div>index 336b0f2..b587639 100644</div><div>--- a/m3-sys/m3front/src/values/Module.m3</div><div>+++ b/m3-sys/m3front/src/values/Module.m3</div><div>@@ -12,7 +12,7 @@ IMPORT M3, M3ID, CG, Value, ValueRep, Scope, Stmt, Error, ESet, External;</div><div> IMPORT Variable, Type, Procedure, Ident, M3Buf, BlockStmt, Int;</div><div> IMPORT Host, Token, Revelation, Coverage, Decl, Scanner, WebInfo;</div><div> IMPORT ProcBody, Target, M3RT, Marker, File, Tracer, Wr;</div><div>-IMPORT WCharr; </div><div>+IMPORT WCharr, Jmpbufs; </div><div> </div><div> FROM Scanner IMPORT GetToken, Fail, Match, MatchID, cur;</div><div> </div><div>@@ -50,6 +50,10 @@ REVEAL</div><div> value_info : Value.T;</div><div> lazyAligned : BOOLEAN;</div><div> containsLazyAlignments: BOOLEAN;</div><div>+ jmpbuf_size : CG.Var := NIL;</div><div>+ alloca : CG.Proc := NIL;</div><div>+ setjmp : CG.Proc := NIL;</div><div>+ jmpbufs : Jmpbufs.Proc;</div><div> OVERRIDES</div><div> typeCheck := TypeCheckMethod;</div><div> set_globals := ValueRep.NoInit;</div><div>@@ -109,6 +113,61 @@ PROCEDURE Reset () =</div><div> INC (compile_age);</div><div> END Reset;</div><div> </div><div>+PROCEDURE GetAlloca (t: T) : CG.Proc =</div><div>+VAR new := FALSE;</div><div>+BEGIN</div><div>+ (* alloca must be special cased by backends to mean</div><div>+ alloca, _alloca, chkstk, etc. *)</div><div>+ IF t.alloca = NIL THEN</div><div>+ t.alloca := CG.Import_procedure (M3ID.Add ("alloca"), 1, CG.Type.Addr,</div><div>+ Target.DefaultCall, new);</div><div>+ IF new THEN</div><div>+ EVAL CG.Declare_param (M3ID.NoID, Target.Word.size, Target.Word.align,</div><div>+ Target.Word.cg_type, 0, in_memory := FALSE,</div><div>+ up_level := FALSE, f := CG.Never);</div><div>+ END;</div><div>+ END;</div><div>+ RETURN t.alloca;</div><div>+END GetAlloca;</div><div>+</div><div>+</div><div>+PROCEDURE GetJmpbufSize (t: T): CG.Var =</div><div>+BEGIN</div><div>+ (* m3_jmpbuf_size is a "constant variable" initialized in </div><div>+ C via:</div><div>+ #include <setjmp.h></div><div>+ extern const m3_jmpbuf_size = sizeof(jmp_buf);</div><div>+ As an optimization, and to avoid any matters involving dynamically</div><div>+ importing data on Win32, Uconstants is always statically linked.</div><div>+ </div><div>+ This isolates the front/middle end from the target.</div><div>+ *)</div><div>+ IF t.jmpbuf_size = NIL THEN</div><div>+ t.jmpbuf_size := CG.Import_global (M3ID.Add ("m3_jmpbuf_size"),</div><div>+ Target.Word.size, Target.Word.align,</div><div>+ Target.Word.cg_type, 0);</div><div>+ END;</div><div>+ RETURN t.jmpbuf_size;</div><div>+END GetJmpbufSize;</div><div>+</div><div>+PROCEDURE GetSetjmp (t: T): CG.Proc =</div><div>+VAR new := FALSE;</div><div>+BEGIN</div><div>+ (* int setjmp(void* ); *)</div><div>+ IF t.setjmp = NIL THEN</div><div>+ t.setjmp := CG.Import_procedure (M3ID.Add (Target.Setjmp), 1,</div><div>+ Target.Integer.cg_type,</div><div>+ Target.DefaultCall, new);</div><div>+ IF new THEN</div><div>+ EVAL CG.Declare_param (M3ID.Add ("jmpbuf"), Target.Address.size,</div><div>+ Target.Address.align, CG.Type.Addr, 0,</div><div>+ in_memory := FALSE, up_level := FALSE,</div><div>+ f := CG.Never);</div><div>+ END;</div><div>+ END;</div><div>+ RETURN t.setjmp;</div><div>+END GetSetjmp;</div><div>+</div><div> PROCEDURE Create (name: M3ID.T): T =</div><div> VAR t: T;</div><div> BEGIN</div><div>@@ -592,8 +651,10 @@ PROCEDURE TypeCheck (t: T; main: BOOLEAN; VAR cs: Value.CheckState) =</div><div> Revelation.TypeCheck (t.revelations);</div><div> Scope.TypeCheck (t.localScope, cs);</div><div> IF (NOT t.interface) THEN</div><div>+ t.jmpbufs := Jmpbufs.CheckProcPush (cs.jmpbufs, 0);</div><div> BlockStmt.CheckTrace (t.trace, cs);</div><div> Stmt.TypeCheck (t.block, cs);</div><div>+ Jmpbufs.CheckProcPop (cs.jmpbufs, t.jmpbufs);</div><div> END;</div><div> </div><div> ESet.Pop (cs, NIL, t.fails, stop := TRUE);</div><div>@@ -1041,6 +1102,7 @@ PROCEDURE EmitBody (x: InitBody) =</div><div> </div><div> (* perform the main body *)</div><div> Tracer.Push (t.trace);</div><div>+ Jmpbufs.CompileProcAllocateJmpbufs (t.jmpbufs);</div><div> EVAL Stmt.Compile (t.block);</div><div> Tracer.Pop (t.trace);</div><div> </div><div>diff --git a/m3-sys/m3front/src/values/Procedure.i3 b/m3-sys/m3front/src/values/Procedure.i3</div><div>index dddb1f3..114a3ec 100644</div><div>--- a/m3-sys/m3front/src/values/Procedure.i3</div><div>+++ b/m3-sys/m3front/src/values/Procedure.i3</div><div>@@ -8,9 +8,9 @@</div><div> </div><div> INTERFACE Procedure;</div><div> </div><div>-IMPORT CG, Value, Type, CallExpr, Decl;</div><div>+IMPORT CG, Value, Type, CallExpr, Decl, M3;</div><div> </div><div>-TYPE T <: Value.T;</div><div>+TYPE T = M3.Procedure; (* <: Value.T *)</div><div> </div><div> PROCEDURE ParseDecl (READONLY att: Decl.Attributes;</div><div> headerOnly: BOOLEAN := FALSE);</div><div>diff --git a/m3-sys/m3front/src/values/Procedure.m3 b/m3-sys/m3front/src/values/Procedure.m3</div><div>index ad0d39c..39df85b 100644</div><div>--- a/m3-sys/m3front/src/values/Procedure.m3</div><div>+++ b/m3-sys/m3front/src/values/Procedure.m3</div><div>@@ -12,7 +12,7 @@ MODULE Procedure;</div><div> IMPORT M3, M3ID, CG, Value, ValueRep, Type, Scope, Error, Host;</div><div> IMPORT ProcType, Stmt, BlockStmt, Marker, Coverage, M3RT;</div><div> IMPORT CallExpr, Token, Variable, ProcExpr, Tracer;</div><div>-IMPORT Scanner, Decl, ESet, ProcBody, Target, Expr, Formal;</div><div>+IMPORT Scanner, Decl, ESet, ProcBody, Target, Expr, Formal, Jmpbufs;</div><div> FROM Scanner IMPORT GetToken, Match, MatchID, cur;</div><div> </div><div> REVEAL</div><div>@@ -33,6 +33,7 @@ REVEAL</div><div> cg_proc : CG.Proc;</div><div> next_cg_proc : T;</div><div> end_origin : INTEGER;</div><div>+ jmpbufs : Jmpbufs.Proc;</div><div> OVERRIDES</div><div> typeCheck := Check;</div><div> set_globals := ValueRep.NoInit;</div><div>@@ -307,7 +308,9 @@ PROCEDURE CheckBody (p: T; VAR cs: Value.CheckState) =</div><div> INC (Type.recursionDepth);</div><div> Scope.TypeCheck (p.syms, cs);</div><div> Marker.PushProcedure (result, p.result, cconv);</div><div>+ p.jmpbufs := Jmpbufs.CheckProcPush (cs.jmpbufs, p.name);</div><div> Stmt.TypeCheck (p.block, cs);</div><div>+ Jmpbufs.CheckProcPop (cs.jmpbufs, p.jmpbufs);</div><div> Marker.Pop ();</div><div> Scope.WarnUnused (p.syms);</div><div> DEC (Type.recursionDepth);</div><div>@@ -574,6 +577,7 @@ PROCEDURE GenBody (p: T) =</div><div> Scope.InitValues (p.syms);</div><div> Scanner.offset := BlockStmt.BodyOffset (p.block);</div><div> Coverage.CountProcedure (p);</div><div>+ Jmpbufs.CompileProcAllocateJmpbufs (p.jmpbufs);</div><div> oc := Stmt.Compile (p.block);</div><div> fallThru := (Stmt.Outcome.FallThrough IN oc);</div><div> EndRaises (p, l, frame, fallThru);</div><div>diff --git a/m3-sys/m3middle/src/M3RT.m3 b/m3-sys/m3middle/src/M3RT.m3</div><div>index 058cea3..463860c 100644</div><div>--- a/m3-sys/m3middle/src/M3RT.m3</div><div>+++ b/m3-sys/m3middle/src/M3RT.m3</div><div>@@ -10,9 +10,9 @@ IMPORT Target;</div><div> </div><div> PROCEDURE Init () =</div><div> VAR</div><div>- IP := Target.Integer.pack;</div><div>- AP := Target.Address.pack;</div><div>- CP := Target.Char.pack;</div><div>+ IP := Target.Integer.pack; (* 32 or 64, same as Target.Address.pack *)</div><div>+ AP := Target.Address.pack; (* 32 or 64, same as Target.Integer.pack *)</div><div>+ CP := Target.Char.pack; (* 8 *)</div><div> BEGIN</div><div> (* closure offsets *)</div><div> CL_marker := 0; (* : INTEGER *)</div><div>@@ -57,8 +57,8 @@ PROCEDURE Init () =</div><div> (* Except, ExceptElse, and Finally frames *)</div><div> EF1_handles := EF_SIZE; (* : ADDRESS *)</div><div> EF1_info := EF1_handles + AP; (* : RTException.Activation *)</div><div>- EF1_jmpbuf := RoundUp (EF1_info + EA_SIZE, 128); (* : jmp_buf *)</div><div>- EF1_SIZE := EF1_jmpbuf + Target.Jumpbuf_size;</div><div>+ EF1_jmpbuf := EF1_info + EA_SIZE; (* : jmp_buf *)</div><div>+ EF1_SIZE := EF1_jmpbuf + AP;</div><div> </div><div> (* FinallyProc frames *)</div><div> EF2_handler := EF_SIZE; (* : ADDRESS (PROC) *)</div><div>@@ -149,10 +149,5 @@ PROCEDURE Init () =</div><div> MUTEX_release := 1 * AP; (*: PROC() *)</div><div> END Init;</div><div> </div><div>-PROCEDURE RoundUp (a, b: INTEGER): INTEGER =</div><div>- BEGIN</div><div>- RETURN (a + b - 1) DIV b * b;</div><div>- END RoundUp;</div><div>-</div><div> BEGIN</div><div> END M3RT.</div><div>diff --git a/m3-sys/m3middle/src/Target.i3 b/m3-sys/m3middle/src/Target.i3</div><div>index c0e5c4c..bd27a07 100644</div><div>--- a/m3-sys/m3middle/src/Target.i3</div><div>+++ b/m3-sys/m3middle/src/Target.i3</div><div>@@ -386,9 +386,6 @@ VAR (*CONST*)</div><div> will cause an address faults. Hence, no explicit NIL checks are needed</div><div> for dereferencing with offsets in this range. *)</div><div> </div><div>- (* Thread stacks *)</div><div>- Jumpbuf_size : CARDINAL; (* size of a "jmp_buf" *)</div><div>-</div><div> (* floating point values *)</div><div> All_floats_legal : BOOLEAN;</div><div> (* If all bit patterns are "legal" floating point values (i.e. they can</div><div>diff --git a/m3-sys/m3middle/src/Target.m3 b/m3-sys/m3middle/src/Target.m3</div><div>index 514a75c..475422f 100644</div><div>--- a/m3-sys/m3middle/src/Target.m3</div><div>+++ b/m3-sys/m3middle/src/Target.m3</div><div>@@ -193,132 +193,11 @@ PROCEDURE Init (system: TEXT; in_OS_name: TEXT; backend_mode: M3BackendMode_t):</div><div> END;</div><div> </div><div> CASE System OF</div><div>- </div><div>- | Systems.ALPHA_LINUX => Jumpbuf_size := 34 * Address.size;</div><div>- | Systems.ALPHA_OPENBSD => Jumpbuf_size := 81 * Address.size;</div><div>- | Systems.ALPHA_OSF => Jumpbuf_size := 84 * Address.size;</div><div>-</div><div>- | Systems.I386_FREEBSD, Systems.FreeBSD4 =></div><div>- Jumpbuf_size := 11 * Address.size;</div><div>-</div><div>- | Systems.AMD64_NETBSD,</div><div>- Systems.AMD64_OPENBSD,</div><div>- Systems.AMD64_FREEBSD =></div><div>- Jumpbuf_size := 12 * Address.size;</div><div>-</div><div>- | Systems.ARM_LINUX,</div><div>- Systems.ARMEL_LINUX =></div><div>- Jumpbuf_size := 64 * Int64.size; (* 392 bytes = 49 * Int64.size on Raspberry Pi *)</div><div>-</div><div>- | Systems.PA32_HPUX =></div><div>- (* 200 bytes with 8 byte alignment *)</div><div>- Jumpbuf_size := 50 * Address.size;</div><div>-</div><div>- | Systems.PA64_HPUX =></div><div>- (* 640 bytes with 16 byte alignment *)</div><div>- Jumpbuf_size := 80 * Address.size;</div><div>-</div><div>- | Systems.MIPS64_OPENBSD,</div><div>- Systems.MIPS64EL_OPENBSD =></div><div>- Jumpbuf_size := 16_53 * Address.size;</div><div>-</div><div>- | Systems.I386_INTERIX =></div><div>-</div><div>- (* Visual C++'s 16 plus 2 ints: is sigmask saved, its value. *)</div><div>-</div><div>- Jumpbuf_size := 18 * Address.size;</div><div>-</div><div>- | Systems.NT386, Systems.I386_NT, Systems.I386_CYGWIN, Systems.I386_MINGW =></div><div>-</div><div>- (* Cygwin: 13, Visual C++: 16, Interix: 18.</div><div>- Use 18 for interop.</div><div>- Cygwin's setjmp.h is wrong by a factor of 4.</div><div>- Cygwin provides setjmp and _setjmp that resolve the same.</div><div>- Visual C++ provides only _setjmp.</div><div>- Visual C++ also has _setjmp3 that the compiler generates</div><div>- a call to. In fact _setjmp appears to only use 8 ints</div><div>- and _setjmp3 appears to use more. Consider using _setjmp3.</div><div>- *)</div><div>- Jumpbuf_size := 18 * Address.size;</div><div> </div><div> | Systems.AMD64_NT =></div><div>- (* 256 bytes with 16 byte alignment *)</div><div>- Jumpbuf_size := 32 * Int64.size;</div><div> Setjmp := "setjmp";</div><div> </div><div>- | Systems.IA64_FREEBSD, Systems.IA64_HPUX,</div><div>- Systems.IA64_LINUX, Systems.IA64_NETBSD, Systems.IA64_NT,</div><div>- Systems.IA64_OPENBSD, Systems.IA64_VMS =></div><div>- (* random guess: 1K *)</div><div>- Jumpbuf_size := 128 * Address.size;</div><div>-</div><div>- | Systems.SPARC32_SOLARIS, Systems.SOLgnu, Systems.SOLsun =></div><div>- (* 76 bytes with 4 byte alignment *)</div><div>- Jumpbuf_size := 19 * Address.size;</div><div>-</div><div>- | Systems.SPARC32_LINUX =></div><div>- Jumpbuf_size := 16_90 * Char.size;</div><div>-</div><div>- | Systems.SPARC64_OPENBSD =></div><div>- Jumpbuf_size := 14 * Address.size;</div><div>-</div><div>- | Systems.SPARC64_LINUX =></div><div>- Jumpbuf_size := 16_280 * Char.size;</div><div>-</div><div>- | Systems.SPARC64_SOLARIS =></div><div>- (* 96 bytes with 8 byte alignment *)</div><div>- Jumpbuf_size := 12 * Address.size;</div><div>-</div><div>- | Systems.I386_SOLARIS =></div><div>- (* 40 bytes with 4 byte alignment *)</div><div>- Jumpbuf_size := 10 * Address.size;</div><div>-</div><div>- | Systems.AMD64_SOLARIS =></div><div>- (* 64 bytes with 8 byte alignment *)</div><div>- Jumpbuf_size := 8 * Address.size;</div><div>-</div><div>- | Systems.I386_LINUX, Systems.LINUXLIBC6 =></div><div>- Jumpbuf_size := 39 * Address.size;</div><div>-</div><div>- | Systems.AMD64_LINUX =></div><div>- Jumpbuf_size := 25 * Address.size;</div><div>-</div><div>- | Systems.I386_DARWIN =></div><div>- Jumpbuf_size := 18 * Address.size;</div><div>-</div><div>- | Systems.AMD64_DARWIN =></div><div>- Jumpbuf_size := ((9 * 2) + 3 + 16) * Int32.size;</div><div>-</div><div>- | Systems.ARM_DARWIN =></div><div>- Jumpbuf_size := 28 * Address.size;</div><div>-</div><div>- | Systems.PPC_DARWIN =></div><div>- Jumpbuf_size := 768 * Word8.size;</div><div>-</div><div>- | Systems.PPC64_DARWIN =></div><div>- Jumpbuf_size := 872 * Word8.size;</div><div>-</div><div>- | Systems.PPC_LINUX => </div><div>- Jumpbuf_size := 74 * Int64.size;</div><div>- (* ideal alignment is 16 bytes, but 4 is ok *)</div><div>-</div><div>- | Systems.PPC32_OPENBSD => </div><div>- Jumpbuf_size := 100 * Address.size;</div><div>-</div><div>- | Systems.I386_NETBSD =></div><div>- Jumpbuf_size := 14 * Address.size; (* 13? *)</div><div>- </div><div>- | Systems.ALPHA32_VMS,</div><div>- Systems.ALPHA64_VMS =></div><div>- Jumpbuf_size := 68 * Word64.size;</div><div>-</div><div>-(* | Systems.I386_MSDOS =></div><div>- Jumpbuf_size := 172 * Char.size; TBD *)</div><div>-</div><div>- | Systems.I386_OPENBSD =></div><div>- Jumpbuf_size := 10 * Address.size;</div><div>-</div><div>- ELSE RETURN FALSE;</div><div>+ ELSE</div><div> END;</div><div> </div><div> InitCallingConventions (backend_mode,</div><div>diff --git a/m3-sys/m3tests/src/p2/p251/Main.m3 b/m3-sys/m3tests/src/p2/p251/Main.m3</div><div>index 998415e..b6d2d30 100644</div><div>--- a/m3-sys/m3tests/src/p2/p251/Main.m3</div><div>+++ b/m3-sys/m3tests/src/p2/p251/Main.m3</div><div>@@ -172,6 +172,70 @@ BEGIN</div><div> TRY F6(); EXCEPT END;</div><div> END Main;</div><div> </div><div>+PROCEDURE Finally () =</div><div>+BEGIN</div><div>+ (* same thing but in FINALLY, and nested FINALLY *)</div><div>+ (* NOTE: This testing is haphazard as I don't</div><div>+ understand exception handling enough to aim for coverage. *)</div><div>+ TRY</div><div>+ top_of_stack := GetStack();</div><div>+ F0();</div><div>+ FINALLY</div><div>+ TRY F1(); EXCEPT ELSE Put("exception " & Int(Line())); NL(); END;</div><div>+ TRY F2(); EXCEPT ELSE Put("exception " & Int(Line())); NL(); END;</div><div>+ TRY F3(); EXCEPT ELSE Put("exception " & Int(Line())); NL(); END;</div><div>+ TRY F4(); EXCEPT END;</div><div>+ TRY F5(); EXCEPT END;</div><div>+ TRY F6(); EXCEPT END;</div><div>+ END;</div><div>+END Finally;</div><div>+</div><div>+PROCEDURE NestedFinally() =</div><div>+BEGIN</div><div>+ (* same thing but in FINALLY, and nested FINALLY *)</div><div>+ (* NOTE: This testing is haphazard as I don't</div><div>+ understand exception handling enough to aim for coverage. *)</div><div>+ TRY</div><div>+ top_of_stack := GetStack();</div><div>+ F0();</div><div>+</div><div>+ FINALLY</div><div>+ TRY TRY F1(); FINALLY F0(); END; EXCEPT ELSE Put("exception " & Int(Line())); NL(); END;</div><div>+ TRY TRY F1(); FINALLY F0(); END; EXCEPT ELSE Put("exception " & Int(Line())); NL(); END;</div><div>+ TRY TRY F1(); FINALLY F0(); END; EXCEPT ELSE Put("exception " & Int(Line())); NL(); END; TRY TRY F1(); FINALLY F0(); END; EXCEPT ELSE Put("exception " & Int(Line())); NL(); END;</div><div>+ </div><div>+ TRY</div><div>+ TRY</div><div>+ F2();</div><div>+ EXCEPT</div><div>+ ELSE</div><div>+ Put("exception " & Int(Line())); NL();</div><div>+ END;</div><div>+ FINALLY</div><div>+ F0();</div><div>+ END; </div><div>+ END;</div><div>+</div><div>+ TRY top_of_stack := GetStack(); TRY F0();</div><div>+ FINALLY TRY F0(); FINALLY F0(); END; END; FINALLY TRY F0(); FINALLY F0(); END; END;</div><div>+ </div><div>+END NestedFinally;</div><div>+</div><div> BEGIN</div><div> Main();</div><div>+</div><div>+ (* same thing but in Module main *)</div><div>+</div><div>+ top_of_stack := GetStack();</div><div>+ F0();</div><div>+ TRY F1(); EXCEPT ELSE Put("exception " & Int(Line())); NL(); END;</div><div>+ TRY F2(); EXCEPT ELSE Put("exception " & Int(Line())); NL(); END;</div><div>+ TRY F3(); EXCEPT ELSE Put("exception " & Int(Line())); NL(); END;</div><div>+ TRY F4(); EXCEPT END;</div><div>+ TRY F5(); EXCEPT END;</div><div>+ TRY F6(); EXCEPT END;</div><div>+ </div><div>+ Finally();</div><div>+ NestedFinally();</div><div>+</div><div> END Main.</div><div><br></div><div><br></div>ok?<div><br></div><div> - Jay<br><br></div> </div></body>
</html>