Hi, An update on Guile 3 hackings over the past couple weeks.
Firstly I made a change to the CPS language. Before, "primcalls" -- invocations of primitives known to the compiler, some of which ultimately compile to instructions/bytecode -- took all arguments as CPS values. This was even the case for primcalls that took known constant arguments, for example a primcall that does a vector-ref of a known index. I made a change so that all primcalls now have an additional slot, which is for some constant data associated with the primcall. (If you need two pieces of constant data, just cons up a data structure.) The idea is that constants used by primcalls as immediates don't need to participate in optimizations in any way -- they should not participate in CSE, have the same lifetime as the primcall so not part of DCE either, and don't need slot allocation. Indirecting them through a named $const binding is complication for no benefit. This change should improve compilation time and memory usage, as the number of labels and variables goes down. I didn't measure much though. I built on that to add set of "throw" primcalls to which all throws and errors compile, with corresponding VM support. This reduces the code size for error branches in functions that do a lot of type checking using e.g. srfi-9 accessors; for example in Guile 2.2, an internal procedure in the assembler (encode-X8_S8_S8_S8) compiles to 158 32-bit words, whereas in 3.0 it is currently 126 words, even after a bit of instruction explosion, and indeed it's a precondition for facilitating more instruction explosion. I also changed the compilation of "ash" to compile to "lsh", "rsh", or a branch between the two. This simplifies things later in the compiler. There are new "tag-fixnum" and "untag-fixnum" instructions, that convert between uint64_t and SCM values without branches. Many instances of scm->u64 etc now compile to these instead. Some unboxed operations and comparisons now operate in the signed range, as it's more convenient to check for fixnums using the fixnum? primcall (which compiles to an instance of the immediate-tag=? instruction) than it is to e.g. check ranges of generic integers, and there is now better support throughout the compiler for s64 values. I removed the <=, >=, and > comparison operators; they can all be expressed in terms of <, though looking back on this now I see that I messed up the behavior with NaN and <= or >=. Damn. Will fix. I added some signed right shift instructions, to do sign-extending right shifts over unboxed values; and that's about it. In summary, a lot of internal plumbing, for what appears to be preparatory work for future stuff. My to-do list in the near term has a few more plumbing-type tasks: * Remove u64=?, as we can just use s64=? polymorphism * Add s64-imm=?, imm-u64<?, u64-imm<?, imm-s64<?, s64-imm<? instructions for unboxed comparisons with immediates * Fix ursh, srsh, ulsh to take only params < 64; their result should be 0 otherwise * Improve the compilation of (= x (logand x #xff)) to hoist fixnum? check * Perhaps add some more /imm instructions for e.g. ulogand, based the compilation of encode-X8_S8_S8_S8 * Fix <= and >= with NaN values * Continue with instruction explosion, starting with vector-ref Cheers, Andy