Index: m3-sys/cm3/src/Builder.m3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/cm3/src/Builder.m3,v retrieving revision 1.37 diff -u -r1.37 Builder.m3 --- m3-sys/cm3/src/Builder.m3 15 Feb 2011 03:02:58 -0000 1.37 +++ m3-sys/cm3/src/Builder.m3 30 Jan 2013 11:54:08 -0000 @@ -13,7 +13,7 @@ IMPORT Quake, QMachine, QValue, QVal, QVSeq; IMPORT M3Loc, M3Unit, M3Options, MxConfig; IMPORT QIdent; -FROM Target IMPORT M3BackendMode_t, BackendAssembly, BackendModeStrings; +FROM Target IMPORT M3BackendMode_t, BackendModeStrings; FROM M3Path IMPORT OSKind, OSKindStrings; IMPORT Pathname; IMPORT QPromise, QPromiseSeq, RefSeq; @@ -1165,7 +1165,11 @@ END CompileS; PROCEDURE CompileC (s: State; u: M3Unit.T) = - VAR tmpS: TEXT; + TYPE Mode_t = M3BackendMode_t; + VAR tmpS: TEXT := NIL; + keep := s.keep_files; + mode := s.m3backend_mode; + boot := s.bootstrap_mode; BEGIN IF (u.kind # UK.C) THEN Merge (s, u) END; @@ -1175,36 +1179,37 @@ ELSIF NOT ObjectIsStale (u) THEN (* already done *) ELSIF (u.kind = UK.C) THEN - IF (s.bootstrap_mode) + IF boot THEN PullForBootstrap (u); ELSE RunCC (s, UnitPath (u), u.object, u.debug, u.optimize); END; Utils.NoteNewFile (u.object); - ELSIF s.bootstrap_mode THEN - CASE s.m3backend_mode OF - | M3BackendMode_t.IntegratedObject, M3BackendMode_t.IntegratedAssembly => + ELSIF boot THEN + CASE mode OF + | Mode_t.IntegratedObject, Mode_t.IntegratedAssembly, Mode_t.C => Msg.FatalError (NIL, "this compiler cannot compile .ic or .mc files"); - | M3BackendMode_t.ExternalObject, M3BackendMode_t.ExternalAssembly => + | Mode_t.ExternalObject, Mode_t.ExternalAssembly => EVAL RunM3Back (s, UnitPath (u), u.object, u.debug, u.optimize); Utils.NoteNewFile (u.object); END; ELSE (* UK.IC or UK.MC *) - CASE s.m3backend_mode OF - | M3BackendMode_t.IntegratedObject, M3BackendMode_t.IntegratedAssembly => + CASE mode OF + | Mode_t.IntegratedObject, Mode_t.IntegratedAssembly, Mode_t.C => Msg.FatalError (NIL, "this compiler cannot compile .ic or .mc files"); - | M3BackendMode_t.ExternalObject => + | Mode_t.ExternalObject => EVAL RunM3Back (s, UnitPath (u), u.object, u.debug, u.optimize); Utils.NoteNewFile (u.object); - | M3BackendMode_t.ExternalAssembly => + | Mode_t.ExternalAssembly => tmpS := TempSName (u); - IF (NOT s.keep_files) THEN Utils.NoteTempFile (tmpS) END; + IF NOT keep THEN Utils.NoteTempFile (tmpS) END; IF RunM3Back (s, UnitPath (u), tmpS, u.debug, u.optimize) AND RunAsm (s, tmpS, u.object) THEN END; - IF (NOT s.keep_files) THEN Utils.Remove (tmpS) END; + IF NOT keep THEN Utils.Remove (tmpS) END; Utils.NoteNewFile (u.object); END; END; + IF NOT keep AND tmpS # NIL THEN Utils.Remove (tmpS) END; END CompileC; PROCEDURE CompileH (s: State; u: M3Unit.T) = @@ -1266,100 +1271,124 @@ BEGIN LOCK utilsMu DO Utils.Remove(rp.nam) END; RETURN 0 END FulfilRP; PROCEDURE PushOneM3 (s: State; u: M3Unit.T): BOOLEAN = + TYPE Mode_t = M3BackendMode_t; VAR - tmpC, tmpS: TEXT; + delC: BOOLEAN; + delS: BOOLEAN; + tmpC: TEXT := NIL; + tmpS: TEXT := NIL; + m3out: TEXT := NIL; + m3backOut: TEXT := NIL; need_merge := FALSE; - plan: [0..7] := ORD(s.m3backend_mode); - BEGIN + mode := s.m3backend_mode; + boot := s.bootstrap_mode; + keep := s.keep_files; + extern := mode = Mode_t.ExternalObject OR mode = Mode_t.ExternalAssembly; + asm := mode = Mode_t.IntegratedAssembly OR mode = Mode_t.ExternalAssembly; + C := mode = Mode_t.C; + delay := s.delayBackend; + BEGIN + <* ASSERT mode # Mode_t.ExternalObject *> (* nonexistant, untested *) + <* ASSERT mode # Mode_t.IntegratedAssembly *> (* nonexistant, untested *) + +(* The idea here is to push along the representation in one of a few sequences. + u.object is where we stop. + Where we stop and what sequence we take depends on the mode of the backend, + and if we are bootstrapping. Bootstrapping runs later phases separately. + Such as assembler or C compiler. + "tmpC" is sometimes C (foo.m3.c, foo.i3.c), sometimes binary representation + of m3cg for input to external backend ("foo.mc" or "foo.ic"). + Options include: + IntegrateObject : m3 => o boot or not (NT/x86) + IntegrateAssembly : m3 => asm => o (no such backends) + boot IntegrateAssembly : m3 => asm (no such backends) + ExternalAssembly : m3 => mc => asm => o + boot ExternalAssembly : m3 => mc => asm + ExternalObject : m3 => mc => o (no such backends, but can with C + m3cgcat) + boot ExternalObject : m3 => mc => o (no such backends, but can with C + m3cgcat, config file would not run assembler) + C : m3 => c => o + boot C : m3 => c +*) u.link_info := NIL; ResetExports (s, u); - IF (s.bootstrap_mode) THEN INC (plan, 4) END; - CASE plan OF - | 0, (* -bootstrap, -m3back, -asm *) - 4, (* +bootstrap, -m3back, -asm *) - 5 => (* +bootstrap, -m3back, +asm *) - IF RunM3 (s, u, u.object) THEN - need_merge := TRUE; - ELSE - IF (NOT s.keep_files) THEN Utils.Remove (u.object) END; - END; + IF C THEN + tmpC := M3Unit.FileName (u) & ".c"; (* ?FUTURE: .cpp *) + END; + IF asm AND NOT boot THEN + tmpS := TempSName (u); + END; + IF extern THEN + tmpC := TempCName (u); + END; + IF C OR extern THEN + m3out := tmpC; + END; - | 1 => (* -bootstrap, -m3back, +asm *) - tmpS := TempSName (u); - IF (NOT s.keep_files) THEN Utils.NoteTempFile (tmpS) END; - IF RunM3 (s, u, tmpS) THEN - EVAL RunAsm (s, tmpS, u.object); - need_merge := TRUE; - END; - IF (NOT s.keep_files) THEN Utils.Remove (tmpS) END; + delC := NOT keep AND NOT (C AND boot) AND tmpC # NIL; + delS := NOT keep AND NOT boot AND tmpS # NIL; - | 2 => (* -bootstrap, +m3back, -asm *) - tmpC := TempCName (u); - IF (NOT s.keep_files) THEN Utils.NoteTempFile (tmpC) END; - IF RunM3 (s, u, tmpC) THEN - EVAL RunM3Back (s, tmpC, u.object, u.debug, u.optimize); - need_merge := TRUE; - END; - IF (NOT s.keep_files) THEN Utils.Remove (tmpC) END; + IF delay THEN + IF delC THEN s.machine.promises.addhi(NEW(NotePromise, nam := tmpC)); END; + IF delS THEN s.machine.promises.addhi(NEW(NotePromise, nam := tmpS)); END; + ELSE + IF delC THEN Utils.NoteTempFile (tmpC) END; + IF delS THEN Utils.NoteTempFile (tmpS) END; + END; + IF mode = Mode_t.IntegratedObject OR (mode = Mode_t.IntegratedAssembly AND boot) THEN + m3out := u.object; + END; - | 3 => (* -bootstrap, +m3back, +asm *) - IF s.delayBackend THEN - (* parallel/delayed version of back-end code *) - tmpC := TempCName (u); - tmpS := TempSName (u); - IF (NOT s.keep_files) THEN - s.machine.promises.addhi(NEW(NotePromise, nam := tmpC)) - END; - IF (NOT s.keep_files) THEN - s.machine.promises.addhi(NEW(NotePromise, nam := tmpS)) - END; + IF mode = Mode_t.IntegratedAssembly AND NOT boot THEN + m3out := tmpS; + END; - IF RunM3 (s, u, tmpC) THEN - s.machine.record(TRUE); - TRY - IF RunM3Back (s, tmpC, tmpS, u.debug, u.optimize) - AND RunAsm (s, tmpS, u.object) THEN - END; - FINALLY - s.machine.record(FALSE) - END; + IF mode = Mode_t.ExternalObject THEN + m3backOut := u.object; + END; + + IF mode = Mode_t.ExternalAssembly THEN + IF boot THEN + m3backOut := u.object; + ELSE + m3backOut := tmpS; + END; + END; - need_merge := TRUE; + IF NOT RunM3 (s, u, m3out) THEN + IF NOT keep THEN Utils.Remove (m3out) END; + Msg.FatalError (NIL, "failed compiling: "); + ELSE + IF s.delayBackend THEN (* parallel/delayed version of back-end code *) + s.machine.record(TRUE); + END; + TRY + IF extern THEN + EVAL RunM3Back (s, tmpC, m3backOut, u.debug, u.optimize); END; - IF (NOT s.keep_files) THEN - s.machine.promises.addhi(NEW(RemovePromise, nam := tmpC)) + IF NOT boot AND C THEN + RunCC (s, tmpC, u.object, TRUE, FALSE); END; - IF (NOT s.keep_files) THEN - s.machine.promises.addhi(NEW(RemovePromise, nam := tmpS)) + IF NOT boot AND asm THEN + EVAL RunAsm (s, tmpS, u.object); + END; + FINALLY + IF s.delayBackend THEN + s.machine.record(FALSE); END; + need_merge := TRUE; + END; + END; - ELSE (* NOT s.delayBackend *) - tmpC := TempCName (u); - tmpS := TempSName (u); - IF (NOT s.keep_files) THEN Utils.NoteTempFile (tmpC) END; - IF (NOT s.keep_files) THEN Utils.NoteTempFile (tmpS) END; - IF RunM3 (s, u, tmpC) THEN - IF RunM3Back (s, tmpC, tmpS, u.debug, u.optimize) - AND RunAsm (s, tmpS, u.object) THEN - END; - need_merge := TRUE; - END; - IF (NOT s.keep_files) THEN Utils.Remove (tmpC) END; - IF (NOT s.keep_files) THEN Utils.Remove (tmpS) END; - END + IF delay THEN + IF delC THEN s.machine.promises.addhi(NEW(RemovePromise, nam := tmpC)) END; + IF delS THEN s.machine.promises.addhi(NEW(RemovePromise, nam := tmpS)) END; + ELSE + IF delS THEN Utils.Remove (tmpS) END; + IF delC THEN Utils.Remove (tmpC) END; + END; - | 6, (* +bootstrap, +m3back, -asm *) - 7 => (* +bootstrap, +m3back, +asm *) - tmpC := TempCName (u); - IF (NOT s.keep_files) THEN Utils.NoteTempFile (tmpC) END; - IF RunM3 (s, u, tmpC) THEN - EVAL RunM3Back (s, tmpC, u.object, u.debug, u.optimize); - need_merge := TRUE; - END; - IF (NOT s.keep_files) THEN Utils.Remove (tmpC) END; - END; (* CASE plan *) Utils.NoteNewFile (u.object); RETURN need_merge; @@ -2138,6 +2167,7 @@ END GenerateCMain; PROCEDURE GenerateCGMain (s: State; Main_O: TEXT) = + TYPE Mode_t = M3BackendMode_t; VAR Main_MC := M3Path.Join (NIL, M3Main, UK.MC); Main_MS := M3Path.Join (NIL, M3Main, UK.MS); @@ -2145,25 +2175,28 @@ init_code: TEXT := NIL; time_O : INTEGER; time_MC : INTEGER; - plan : [0..3] := 0; + mode := s.m3backend_mode; + keep := s.keep_files; BEGIN - CASE s.m3backend_mode OF - | M3BackendMode_t.IntegratedObject => (* -m3back, -asm => cg produces object code *) + CASE mode OF + + | Mode_t.C => + Msg.FatalError (NIL, "use 'main_in_c' with C backend "); + + | Mode_t.IntegratedObject => (* -m3back, -asm => cg produces object code *) GenCGMain (s, Main_O); - Utils.NoteNewFile (Main_O); - | M3BackendMode_t.IntegratedAssembly => (* -m3back, +asm => cg produces assembly code *) + | Mode_t.IntegratedAssembly => (* -m3back, +asm => cg produces assembly code *) (* don't mess with a file comparison, just build the stupid thing... *) GenCGMain (s, Main_MS); ETimer.Pop (); Msg.Debug ("assembling ", Main_MC, " ...", Wr.EOL); EVAL RunAsm (s, Main_MS, Main_O); - IF (NOT s.keep_files) THEN Utils.Remove (Main_MS); END; - Utils.NoteNewFile (Main_O); + IF NOT keep THEN Utils.Remove (Main_MS); END; - | M3BackendMode_t.ExternalObject, (* +m3back, -asm => cg produces il, m3back produces object *) - M3BackendMode_t.ExternalAssembly => (* +m3back, +asm => cg produces il, m3back produces assembly *) + | Mode_t.ExternalObject, (* +m3back, -asm => cg produces il, m3back produces object *) + Mode_t.ExternalAssembly => (* +m3back, +asm => cg produces il, m3back produces assembly *) (* check for an up-to-date Main_O *) time_O := Utils.LocalModTime (Main_O); time_MC := Utils.LocalModTime (Main_MC); @@ -2187,19 +2220,20 @@ Utils.Remove (Main_XX); END; Msg.Debug ("compiling ", Main_MC, " ...", Wr.EOL); - IF (plan = 2) THEN + IF mode = Mode_t.ExternalAssembly THEN + <* ASSERT FALSE *> EVAL RunM3Back (s, Main_MC, Main_O, debug := TRUE, optimize := FALSE); ELSE IF RunM3Back (s, Main_MC, Main_MS, debug := TRUE, optimize := FALSE) AND RunAsm (s, Main_MS, Main_O) THEN END; - IF (NOT s.keep_files) THEN Utils.Remove (Main_MS); END; + IF NOT keep THEN Utils.Remove (Main_MS); END; END; - Utils.NoteNewFile (Main_O); Utils.NoteNewFile (Main_MC); END; END; (* CASE plan *) + Utils.NoteNewFile (Main_O); END GenerateCGMain; PROCEDURE GenCGMain (s: State; object: TEXT) = @@ -2956,9 +2990,14 @@ END TempSName; PROCEDURE ObjectName (s: State; u: M3Unit.T): TEXT = + TYPE Mode_t = M3BackendMode_t; VAR ext := u.kind; + mode := s.m3backend_mode; + boot := s.bootstrap_mode; + asm := mode = Mode_t.IntegratedAssembly OR mode = Mode_t.ExternalAssembly; + C := mode = Mode_t.C; BEGIN - IF NOT s.bootstrap_mode THEN + IF NOT boot THEN (* produce object modules *) CASE ext OF | UK.I3, UK.IC, UK.IS => ext := UK.IO; @@ -2967,8 +3006,15 @@ | UK.IO, UK.MO, UK.O => RETURN M3Unit.FileName (u); ELSE RETURN NIL; END; + + ELSIF C THEN + CASE ext OF + | UK.I3, UK.M3 => RETURN M3Unit.FileName (u) & ".c"; (* ?FUTURE: .cpp *) + | UK.C, UK.S, UK.H => (* skip *) + | UK.IO, UK.MO, UK.O => (* skip *) + END; - ELSIF BackendAssembly[s.m3backend_mode] THEN + ELSIF asm THEN (* bootstrap with an assembler *) CASE ext OF | UK.I3, UK.IC, UK.IS => ext := UK.IS; Index: m3-sys/cm3/src/M3Backend.m3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/cm3/src/M3Backend.m3,v retrieving revision 1.5 diff -u -r1.5 M3Backend.m3 --- m3-sys/cm3/src/M3Backend.m3 26 Sep 2012 07:39:19 -0000 1.5 +++ m3-sys/cm3/src/M3Backend.m3 30 Jan 2013 11:54:08 -0000 @@ -6,7 +6,7 @@ MODULE M3Backend; -IMPORT Wr, Thread; +IMPORT Wr, Thread, M3C; IMPORT M3CG, Msg, Utils, NTObjFile, M3x86, M3ObjFile; IMPORT M3CG_BinWr; FROM Target IMPORT M3BackendMode_t, BackendIntegrated; @@ -20,6 +20,9 @@ PROCEDURE Open (target: Wr.T; target_name: TEXT; backend_mode: M3BackendMode_t): M3CG.T = BEGIN + IF backend_mode = M3BackendMode_t.C THEN + RETURN M3C.New (target); + END; IF NOT BackendIntegrated[backend_mode] THEN RETURN M3CG_BinWr.New (target); END; Index: m3-sys/cm3/src/M3Build.m3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/cm3/src/M3Build.m3,v retrieving revision 1.45 diff -u -r1.45 M3Build.m3 --- m3-sys/cm3/src/M3Build.m3 2 Dec 2010 16:04:23 -0000 1.45 +++ m3-sys/cm3/src/M3Build.m3 30 Jan 2013 11:54:09 -0000 @@ -6,7 +6,7 @@ IMPORT Env, IntArraySort, IntRefTbl, M3ID, Pathname, Text, TextList, Thread, Wr; IMPORT Quake, QValue, QCode, QMachine, QVal, QVSeq, QVTbl, M3Timers; IMPORT Arg, Builder, M3Loc, M3Options, M3Path, M3Unit, Msg, Utils; -FROM QMachine IMPORT PushText, PopText, PopID, PopBool; +FROM QMachine IMPORT PushBool, PushText, PopText, PopID, PopBool; IMPORT MxConfig; IMPORT OSError, Process, Dirs, TextUtils; @@ -365,6 +365,8 @@ CONST Builtins = ARRAY OF Builtin { +(*------------------------------------------------- feature/version probes --*) + Builtin {"HasCBackend", HasCBackend, 0, TRUE }, (* packages & locations *) Builtin {"Pkg", DoPkg, 1, TRUE}, Builtin {"override", DoOverride, 2, FALSE}, @@ -577,6 +579,14 @@ t.put (M3ID.Add (nm), v); END DefineArray; +(*------------------------------------------------- feature/version probes --*) + +PROCEDURE HasCBackend (m: QMachine.T; <*UNUSED*> n_args: INTEGER) = + VAR t := Self (m); + BEGIN + PushBool (t, TRUE); + END HasCBackend; + (*------------------------------------------------------ package locations --*) PROCEDURE DoPkg (m: QMachine.T; <*UNUSED*> n_args: INTEGER) Index: m3-sys/m3middle/src/Target.i3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/Target.i3,v retrieving revision 1.72 diff -u -r1.72 Target.i3 --- m3-sys/m3middle/src/Target.i3 24 Dec 2012 20:11:06 -0000 1.72 +++ m3-sys/m3middle/src/Target.i3 30 Jan 2013 11:54:09 -0000 @@ -138,7 +138,8 @@ IntegratedObject, (* "0" -- don't call m3_backend, M3CG produces object code *) IntegratedAssembly, (* "1" -- don't call m3_backend, M3CG produces assembly code *) ExternalObject, (* "2" -- call m3_backend, it produces object code *) - ExternalAssembly (* "3" -- call m3_backend, it produces assembly code *) + ExternalAssembly, (* "3" -- call m3_backend, it produces assembly code *) + C (* -- don't call m3_backend, call compile_c, M3CG produces C *) }; CONST @@ -146,10 +147,11 @@ { "IntegratedObject", "IntegratedAssembly", "ExternalObject", - "ExternalAssembly" }; + "ExternalAssembly", + "C" }; - BackendIntegrated = ARRAY M3BackendMode_t OF BOOLEAN { TRUE, TRUE, FALSE, FALSE }; - BackendAssembly = ARRAY M3BackendMode_t OF BOOLEAN { FALSE, TRUE, FALSE, TRUE }; + BackendIntegrated = ARRAY M3BackendMode_t OF BOOLEAN { TRUE, TRUE, FALSE, FALSE, TRUE }; + (* BackendAssembly = ARRAY M3BackendMode_t OF BOOLEAN { FALSE, TRUE, FALSE, TRUE, FALSE }; *) (*-------------------------------------------------------- initialization ---*) Index: m3-sys/m3middle/src/Target.m3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/Target.m3,v retrieving revision 1.128 diff -u -r1.128 Target.m3 --- m3-sys/m3middle/src/Target.m3 20 Dec 2012 04:41:14 -0000 1.128 +++ m3-sys/m3middle/src/Target.m3 30 Jan 2013 11:54:09 -0000 @@ -355,20 +355,25 @@ END Init; PROCEDURE InitCallingConventions(backend_mode: M3BackendMode_t; - calling_conventions: BOOLEAN) = + target_has_calling_conventions: BOOLEAN) = PROCEDURE New(name: TEXT; id: [0..1]): CallingConvention = VAR cc := NEW(CallingConvention, name := name); BEGIN - (* The external backend handles more calling convention details than the - integrated backend -- reversing parameter order and knowing how to - return structs. *) - IF calling_conventions THEN + (* This stuff seems messed up. *) + IF (*backend_mode = M3BackendMode_t.C OR*) target_has_calling_conventions THEN cc.m3cg_id := id; - cc.args_left_to_right := NOT integrated; - cc.results_on_left := TRUE; - cc.standard_structs := NOT integrated; ELSE cc.m3cg_id := 0; + END; + IF backend_mode = M3BackendMode_t.C THEN + cc.args_left_to_right := TRUE; + cc.results_on_left := TRUE; + cc.standard_structs := TRUE; + ELSIF integrated THEN + cc.args_left_to_right := FALSE; + cc.results_on_left := TRUE; + cc.standard_structs := FALSE; + ELSE cc.args_left_to_right := TRUE; cc.results_on_left := FALSE; cc.standard_structs := TRUE;