So later today will probably be generation of machine code, which means the
FragmentBuilder and the associated classes for output of machine code. At
least with the split off expanded handler I can implement that rather simply
then later on when I want something optimized I can generate machine code.
I can also handle stuff such as software floating point and other
virtualized operations if a given CPU does not support certain things. The
only thing is then is when it comes to register sizes and such. Some target
architectures I plan on supporting, such as the Z80, only have mostly
8-bit registers and a small number of them. I could actually cheat though.
The naive translator could always not support anything below 32-bit and
have it require registers with a size of at least 32-bits. For 8-bit systems
since virtually every operation would be 32-bits in size, there would need
to be some kind of optimization to prevent blatant waste of resources. But
actually, there could be an 8-bit and 16-bit filter that is used after the
given output. I think that would be the best route to be honest. Maybe for
the 8-bit/16-bit, instead of it being an expanded thing I can instead just
have it be a
MachineCodeOutput that can be layered. Basically when the
MachineCodeOutput is to be initialized from a config, if the target is a
8-bit or 16-bit system then the native output would be wrapped. Then it
would handle virtualizing registers and expanding any needed mathematical
operations as required. It would be a bit of a kludge but it could work. At
least the 8-bit/16-bit handler would be standalone. Then the native output
would not need to handle
long operations (which would result in
The translators would always pretty much write to
anyway, at least mine would. The translators just take the expanded byte code
and make operations from them.
However, the low bits filter could be used for every CPU that is below 64-bits
since Java does have
long. It would pretty much be write once in a way.
I can probably handle default values a bit better if I had a linear process of
handling them. Basically if I did not make the
Map, I could
instead have it where a get of any value will return something specific
depending on the internal value or derived values.
JITConfig is not a
Map so that is good.
I am thinking that perhaps I should target x86 first. That is where most of the user base today is on and having extra users could be useful to be honest. Other architectures could follow after that. At least with more users it would be much easier to find issues because there would be a larger pool of users.
I could make SquirrelJME output an object that is linked but that would be a
bit messy. One thing about writing a compiler is the various ABIs for variants
of systems. For example, I should link with the C library dynamically although
I could use a static library. I should probably keep my library footprint to
a minimum. One big thing though with native calls is how methods are treated
and such. I suppose what I would need is special JIT library glue which
matches a target API and provides an interface for execution. Basically
something which wraps C level API and is in a way auto-generated so to speak.
I would say that this stuff goes into unsafe and is kept hidden. When the
SquirrelJME wishes to do things, it forwards to that. But thinking
about it, having everything in a single class is a bit ugly, I can split it
up. Basically, I can have the unsafe package have quite a number of classes
where internal stuff is specially crafted.
Basically, I have a bunch of outer exposed classes. These then forward their
calls to internal classes. So
SquirrelJME calls into
doing some basic checks. However any call to
__SquirrelJME__ would then
instead call elsewhere, so it would just be rewritten to another class that
handles the things. Then that class would instead call other architecture
specific code. I could probably have a special naming setup for the class
rewriting. Perhaps just
Foo is a class which can be
So anything that is operating specific that cannot internally be handled by
SquirrelJME is to be removed. This would be like standard
output and stuff like getting the current time or killing the VM.
I wonder if I should nuke mailboxes. They do work but I wonder if I should
keep them or move them around in a way where they work via the
and where the build system can use the same exact code.
The mailboxes are used by IMC though, so I need those. I will just commonize
their code between the build system and SquirrelJME. At least with this, I can
make it so that I only need to implement the
__Ext_ classes in the build
system while they can still be rewritten as such.
Going to use a new checked exception for mailbox failures. This would make things much easier personally.
Ok so now I have common code between the build system and SquirrelJME, which is good, because the nastily duplicated interfaces were a bit ugly.
So now system services can be looked up via properties so they can be overidden if needed.
systemService should not belong in
SystemVM? Because that is
very much an OS related thing. Maybe instead add an
handles that. The VM I want to be very OS independent as it can just be
machine code for a target.