On Wed, May 25, 2022 at 9:50 PM Gaius Mulley <gaiusm...@gmail.com> wrote: > > Richard Biener <richard.guent...@gmail.com> writes: > > > So is there a reason to have the 'scaffold' separate from the object > > of hello.mod? > > Perhaps the major advantage is flexibility? But no we can by default > produce the scaffold within the object of hello.mod (and give users the > ability to disable scaffold generation should they wish to implement > their own). > > > Is there more than a 1:1 relation between a .mod and the 'scaffold'? > > yes there is a 1:1 relation between a .mod and the scaffold. Although > the caveat is that the compiler would need to parse every .def and .mod > imports from the application universe. Not a major change as gm2 has > the ability to do whole program (application) compiling, so a minor set > of changes to ensure that upon compiling the program module that it also > parses every .def/.mod. > > > Why are multiple tools involved here - can the m2 frontend not parse > > imports, reorder runtime modules and generate the 'scaffold' as > > GENERIC IL as part of the translation unit of the .mod file? > > Indirection through emitting C++ source code makes the process a bit > > awkward IMHO. > > indeed the m2 front end can parse imports, reorder and generate the > scaffold. > > > Unfortunately I have no m2 installation around to look at how complex > > the 'scaffold' is. > > the scaffold is really simple for example here it is for hello.mod: > > $ gm2 -c -g -fmakelist hello.mod > $ cat hello.lst > Storage > SYSTEM > M2RTS > RTExceptions > # libc 11 > /home/gaius/opt/lib/gcc/x86_64-pc-linux-gnu/13.0.0/m2/m2pim/libc.def FOR 'C' > # SYSTEM 11 > /home/gaius/opt/lib/gcc/x86_64-pc-linux-gnu/13.0.0/m2/m2pim/SYSTEM.mod > # StrIO 11 > /home/gaius/opt/lib/gcc/x86_64-pc-linux-gnu/13.0.0/m2/m2pim/StrIO.mod > # StrLib 10 > /home/gaius/opt/lib/gcc/x86_64-pc-linux-gnu/13.0.0/m2/m2pim/StrLib.mod > # ASCII 10 > /home/gaius/opt/lib/gcc/x86_64-pc-linux-gnu/13.0.0/m2/m2pim/ASCII.mod > # NumberIO 10 > /home/gaius/opt/lib/gcc/x86_64-pc-linux-gnu/13.0.0/m2/m2pim/NumberIO.mod > # Indexing 10 > /home/gaius/opt/lib/gcc/x86_64-pc-linux-gnu/13.0.0/m2/m2pim/Indexing.mod > # errno 9 > /home/gaius/opt/lib/gcc/x86_64-pc-linux-gnu/13.0.0/m2/m2pim/errno.def > # termios 9 > /home/gaius/opt/lib/gcc/x86_64-pc-linux-gnu/13.0.0/m2/m2pim/termios.def > # FIO 9 /home/gaius/opt/lib/gcc/x86_64-pc-linux-gnu/13.0.0/m2/m2pim/FIO.mod > # IO 8 /home/gaius/opt/lib/gcc/x86_64-pc-linux-gnu/13.0.0/m2/m2pim/IO.mod > # StdIO 7 > /home/gaius/opt/lib/gcc/x86_64-pc-linux-gnu/13.0.0/m2/m2pim/StdIO.mod > # Debug 6 > /home/gaius/opt/lib/gcc/x86_64-pc-linux-gnu/13.0.0/m2/m2pim/Debug.mod > # SysStorage 5 > /home/gaius/opt/lib/gcc/x86_64-pc-linux-gnu/13.0.0/m2/m2pim/SysStorage.mod > # SysExceptions 4 > /home/gaius/opt/lib/gcc/x86_64-pc-linux-gnu/13.0.0/m2/m2pim/SysExceptions.def > # M2EXCEPTION 4 > /home/gaius/opt/lib/gcc/x86_64-pc-linux-gnu/13.0.0/m2/m2pim/M2EXCEPTION.mod > # Storage 4 > /home/gaius/opt/lib/gcc/x86_64-pc-linux-gnu/13.0.0/m2/m2pim/Storage.mod > # RTExceptions 3 > /home/gaius/opt/lib/gcc/x86_64-pc-linux-gnu/13.0.0/m2/m2pim/RTExceptions.mod > # M2RTS 2 > /home/gaius/opt/lib/gcc/x86_64-pc-linux-gnu/13.0.0/m2/m2pim/M2RTS.mod > # hello 1 hello.mod > # > # Initialization order > # > StrIO > StrLib > ASCII > NumberIO > Indexing > errno > termios > FIO > IO > StdIO > Debug > SysStorage > SysExceptions > M2EXCEPTION > hello > > and now to generate the scaffold for a static application: > > $ ~/opt/bin/gm2 -fmakeinit -c -g hello.mod > $ cat hello_m2.cpp > extern "C" void exit(int); > > extern "C" void RTExceptions_DefaultErrorCatch(void); > extern "C" void _M2_Storage_init (int argc, char *argv[]); > extern "C" void _M2_Storage_finish (void); > extern "C" void _M2_SYSTEM_init (int argc, char *argv[]); > extern "C" void _M2_SYSTEM_finish (void); > extern "C" void _M2_M2RTS_init (int argc, char *argv[]); > extern "C" void _M2_M2RTS_finish (void); > extern "C" void _M2_RTExceptions_init (int argc, char *argv[]); > extern "C" void _M2_RTExceptions_finish (void); > extern "C" void _M2_StrIO_init (int argc, char *argv[]); > extern "C" void _M2_StrIO_finish (void); > extern "C" void _M2_StrLib_init (int argc, char *argv[]); > extern "C" void _M2_StrLib_finish (void); > extern "C" void _M2_ASCII_init (int argc, char *argv[]); > extern "C" void _M2_ASCII_finish (void); > extern "C" void _M2_NumberIO_init (int argc, char *argv[]); > extern "C" void _M2_NumberIO_finish (void); > extern "C" void _M2_Indexing_init (int argc, char *argv[]); > extern "C" void _M2_Indexing_finish (void); > extern "C" void _M2_errno_init (int argc, char *argv[]); > extern "C" void _M2_errno_finish (void); > extern "C" void _M2_termios_init (int argc, char *argv[]); > extern "C" void _M2_termios_finish (void); > extern "C" void _M2_FIO_init (int argc, char *argv[]); > extern "C" void _M2_FIO_finish (void); > extern "C" void _M2_IO_init (int argc, char *argv[]); > extern "C" void _M2_IO_finish (void); > extern "C" void _M2_StdIO_init (int argc, char *argv[]); > extern "C" void _M2_StdIO_finish (void); > extern "C" void _M2_Debug_init (int argc, char *argv[]); > extern "C" void _M2_Debug_finish (void); > extern "C" void _M2_SysStorage_init (int argc, char *argv[]); > extern "C" void _M2_SysStorage_finish (void); > extern "C" void _M2_SysExceptions_init (int argc, char *argv[]); > extern "C" void _M2_SysExceptions_finish (void); > extern "C" void _M2_M2EXCEPTION_init (int argc, char *argv[]); > extern "C" void _M2_M2EXCEPTION_finish (void); > extern "C" void _M2_hello_init (int argc, char *argv[]); > extern "C" void _M2_hello_finish (void); > > extern "C" void M2RTS_ExecuteTerminationProcedures(void); > > extern "C" void M2RTS_ExecuteInitialProcedures(void); > > static void init (int argc, char *argv[]) > { > try { > _M2_Storage_init (argc, argv); > _M2_SYSTEM_init (argc, argv); > _M2_M2RTS_init (argc, argv); > _M2_RTExceptions_init (argc, argv); > _M2_StrIO_init (argc, argv); > _M2_StrLib_init (argc, argv); > _M2_ASCII_init (argc, argv); > _M2_NumberIO_init (argc, argv); > _M2_Indexing_init (argc, argv); > _M2_errno_init (argc, argv); > _M2_termios_init (argc, argv); > _M2_FIO_init (argc, argv); > _M2_IO_init (argc, argv); > _M2_StdIO_init (argc, argv); > _M2_Debug_init (argc, argv); > _M2_SysStorage_init (argc, argv); > _M2_SysExceptions_init (argc, argv); > _M2_M2EXCEPTION_init (argc, argv); > M2RTS_ExecuteInitialProcedures (); > _M2_hello_init (argc, argv); > } > catch (...) { > RTExceptions_DefaultErrorCatch(); > } > } > > static void finish (void) > { > try { > M2RTS_ExecuteTerminationProcedures (); > _M2_hello_finish (); > _M2_M2EXCEPTION_finish (); > _M2_SysExceptions_finish (); > _M2_SysStorage_finish (); > _M2_Debug_finish (); > _M2_StdIO_finish (); > _M2_IO_finish (); > _M2_FIO_finish (); > _M2_termios_finish (); > _M2_errno_finish (); > _M2_Indexing_finish (); > _M2_NumberIO_finish (); > _M2_ASCII_finish (); > _M2_StrLib_finish (); > _M2_StrIO_finish (); > _M2_RTExceptions_finish (); > _M2_M2RTS_finish (); > _M2_SYSTEM_finish (); > _M2_Storage_finish (); > exit (0); > } > catch (...) { > RTExceptions_DefaultErrorCatch(); > } > } > > int main (int argc, char *argv[]) > { > init (argc, argv); > finish (); > return (0); > } > > > or similarly for a shared library: > > $ ~/opt/bin/gm2 -fshared -fmakeinit -c -g hello.mod > $ cat hello_m2.cpp > extern "C" void exit(int); > > extern "C" void RTExceptions_DefaultErrorCatch(void); > extern "C" void _M2_Storage_init (int argc, char *argv[]); > extern "C" void _M2_Storage_finish (void); > extern "C" void _M2_SYSTEM_init (int argc, char *argv[]); > extern "C" void _M2_SYSTEM_finish (void); > extern "C" void _M2_M2RTS_init (int argc, char *argv[]); > extern "C" void _M2_M2RTS_finish (void); > extern "C" void _M2_RTExceptions_init (int argc, char *argv[]); > extern "C" void _M2_RTExceptions_finish (void); > extern "C" void _M2_StrIO_init (int argc, char *argv[]); > extern "C" void _M2_StrIO_finish (void); > extern "C" void _M2_StrLib_init (int argc, char *argv[]); > extern "C" void _M2_StrLib_finish (void); > extern "C" void _M2_ASCII_init (int argc, char *argv[]); > extern "C" void _M2_ASCII_finish (void); > extern "C" void _M2_NumberIO_init (int argc, char *argv[]); > extern "C" void _M2_NumberIO_finish (void); > extern "C" void _M2_Indexing_init (int argc, char *argv[]); > extern "C" void _M2_Indexing_finish (void); > extern "C" void _M2_errno_init (int argc, char *argv[]); > extern "C" void _M2_errno_finish (void); > extern "C" void _M2_termios_init (int argc, char *argv[]); > extern "C" void _M2_termios_finish (void); > extern "C" void _M2_FIO_init (int argc, char *argv[]); > extern "C" void _M2_FIO_finish (void); > extern "C" void _M2_IO_init (int argc, char *argv[]); > extern "C" void _M2_IO_finish (void); > extern "C" void _M2_StdIO_init (int argc, char *argv[]); > extern "C" void _M2_StdIO_finish (void); > extern "C" void _M2_Debug_init (int argc, char *argv[]); > extern "C" void _M2_Debug_finish (void); > extern "C" void _M2_SysStorage_init (int argc, char *argv[]); > extern "C" void _M2_SysStorage_finish (void); > extern "C" void _M2_SysExceptions_init (int argc, char *argv[]); > extern "C" void _M2_SysExceptions_finish (void); > extern "C" void _M2_M2EXCEPTION_init (int argc, char *argv[]); > extern "C" void _M2_M2EXCEPTION_finish (void); > extern "C" void _M2_hello_init (int argc, char *argv[]); > extern "C" void _M2_hello_finish (void); > > extern "C" void M2RTS_ExecuteTerminationProcedures(void); > > extern "C" void M2RTS_ExecuteInitialProcedures(void); > > static void init (int argc, char *argv[]) > { > try { > _M2_Storage_init (argc, argv); > _M2_SYSTEM_init (argc, argv); > _M2_M2RTS_init (argc, argv); > _M2_RTExceptions_init (argc, argv); > _M2_StrIO_init (argc, argv); > _M2_StrLib_init (argc, argv); > _M2_ASCII_init (argc, argv); > _M2_NumberIO_init (argc, argv); > _M2_Indexing_init (argc, argv); > _M2_errno_init (argc, argv); > _M2_termios_init (argc, argv); > _M2_FIO_init (argc, argv); > _M2_IO_init (argc, argv); > _M2_StdIO_init (argc, argv); > _M2_Debug_init (argc, argv); > _M2_SysStorage_init (argc, argv); > _M2_SysExceptions_init (argc, argv); > _M2_M2EXCEPTION_init (argc, argv); > M2RTS_ExecuteInitialProcedures (); > _M2_hello_init (argc, argv); > } > catch (...) { > RTExceptions_DefaultErrorCatch(); > } > } > > static void finish (void) > { > try { > M2RTS_ExecuteTerminationProcedures (); > _M2_hello_finish (); > _M2_M2EXCEPTION_finish (); > _M2_SysExceptions_finish (); > _M2_SysStorage_finish (); > _M2_Debug_finish (); > _M2_StdIO_finish (); > _M2_IO_finish (); > _M2_FIO_finish (); > _M2_termios_finish (); > _M2_errno_finish (); > _M2_Indexing_finish (); > _M2_NumberIO_finish (); > _M2_ASCII_finish (); > _M2_StrLib_finish (); > _M2_StrIO_finish (); > _M2_RTExceptions_finish (); > _M2_M2RTS_finish (); > _M2_SYSTEM_finish (); > _M2_Storage_finish (); > exit (0); > } > catch (...) { > RTExceptions_DefaultErrorCatch(); > } > } > > int main (int argc, char *argv[]) > { > init (argc, argv); > finish (); > return (0); > }
So seeing the above the scaffold is only generated for the main program translation unit - I suppose an application can consist of more than one translation unit. And the main TU compilation (recursively) will import all other TUs (but they are compiled separately?). Is there a well-defined order the module initialization has to happen across a program? I'm thinking of each m2 TU adding to a global initialization / finalization vector thus adding static initvec[] __attribute__((section("m2init"))) = { _M2_..._init, _M2_..._init, ... }; static finivec[] __attribute__((section("m2fini"))) = { _M2_..._finish, __M2_..._finish, ...}; and the main program just calling into the m2 runtime with the address of the sections which the would apply runtime sorting to weed out duplicates (or have the individual _init/_finish protect against multiple invocations). That's of course harder if the initialization/finalization order is well-defined across the import graph (or tree). Of course the module objects could also emit meta-data so the runtime can replicate the import graph. Not sure if optimizing the compile or the runtime is more important here. > yes indeed all these programs could be placed into the front end, > producing an IR GENERIC scaffold by default It does look quite managable to create the above indeed. You might want to look into the C++ frontend creating global variable initialization/finalization functions for a TU like struct X { X(); ~X(); } x; Richard. > > regards, > Gaius