> What I understand from that is, byte code is portable while machine code isn't.
This is an area I want to explore. It seems to me that it is less true than it used to be. x86_32 was the last significant architecture that made things hard. Now we can ignore that. All desktop or server class CPUs support 8, 16, 32 and 64-bit integers. And they all have at least 10 general purpose registers. They all have a sensible set of memory access modes. As a result, the same code generator works for them all. As it stands, my code generator calls functions like emit_indexed_load, emit_conditional_jump etc. There are currently 26 of those functions and they're all trivial.
So far I have only implemented them for x86_64 machine code output. But writing versions that output ARM64 or risvc doesn't seem hard. I expect I'll find small problems which will cause me to have to tweak the set of CPU features my code gen depends on.
As for generating bytecode being easier than x86_64 machine code, I disagree. There are lots of tools for validating x86_64 machine code (ie disassemblers). There aren't any for a bytecode I might invent. And I can ask an AI how to generate x86_64 machine code to do an indexed load. I immediately get the answer. I don't have to think about how to make an efficient bytecode encoding.
The hardest thing I've encountered so far is getting the ABI right so that my compiled code can call existing functions (eg libc). But I'd have to do that even if I was using an interpreter.
This is an area I want to explore. It seems to me that it is less true than it used to be. x86_32 was the last significant architecture that made things hard. Now we can ignore that. All desktop or server class CPUs support 8, 16, 32 and 64-bit integers. And they all have at least 10 general purpose registers. They all have a sensible set of memory access modes. As a result, the same code generator works for them all. As it stands, my code generator calls functions like emit_indexed_load, emit_conditional_jump etc. There are currently 26 of those functions and they're all trivial.
So far I have only implemented them for x86_64 machine code output. But writing versions that output ARM64 or risvc doesn't seem hard. I expect I'll find small problems which will cause me to have to tweak the set of CPU features my code gen depends on.
As for generating bytecode being easier than x86_64 machine code, I disagree. There are lots of tools for validating x86_64 machine code (ie disassemblers). There aren't any for a bytecode I might invent. And I can ask an AI how to generate x86_64 machine code to do an indexed load. I immediately get the answer. I don't have to think about how to make an efficient bytecode encoding.
The hardest thing I've encountered so far is getting the ABI right so that my compiled code can call existing functions (eg libc). But I'd have to do that even if I was using an interpreter.