opcodes that take a variadic number of arguments are difficult to work with. Some examples of these (maybe the only examples of them) are set_args, get_params, set_returns, and get_results. These ops take lists of values to pass/receive in a call. The first arg to the op is a string or an FIA that contains information about the number of ops that follow.
At the very least, these ops should be flagged to identify them as being special. This way a PIR-based disassembler can identify them and produce a better listing.
Far better idea, in my mind, would be refactoring these ops entirely so that they no longer take variadic lists of arguments. Instead, I suggest we could have IMCC build CallContext PMCs (or a new kind of proto-CallSignature PMC instead, depending on preprocessing requirements) at compile time and store them in the constants table. So set_args_p would change from taking an FIA with a series of flags and then a variadic argument list to taking a single "CallArguments" PMC which would contain all the same information, but in a form that was much easier to work with. Since information about the arguments to a function call are already stored as constants in the bytecode stream directly, we can easily convert this to a PMC constant with no loss of dynamicism. If anything we gain more dynamicism because we gain the ability to construct argument lists at runtime without having to explicitly use :flat.
These kinds of refactors would dovetail nicely with other PCC refactors currently planned.
These opcodes are already magical, in that they don't actually take a FIA as the first argument, they take a string and convert it into an FIA.
Completely removing the magic would require a separate opcode call for each arg, which is unnecessarily expensive. The general idea (I discussed it with bacek during the CallContext refactor, but it doesn't look like I documented it anywhere) is to push the magic further: instead of creating a FIA and using it to directly poke into the opcode memory in set_args, etc, IMCC will create the CallContext directly from the signature string and following arguments. The signature would still be a single PMC argument, just a CallContext argument instead of an FIA.
One possible way of "regularizing" the magic would be to say that set_args, etc always and only take a single PMC argument (a CallContext), and introduce some new syntax to PIR for aggregate creation.
.local pmc array, hash, callrecord
array = ( 'a', 'b', 3, 4 )
hash = ( 'foo' => 'bar', 'baz' => 1 )
callrecord = ( 'hello', 'name' => 'Fred' ) :call_sig('SSnS')
It's not particularly strange, since it's pretty much the same syntax we use now for subroutine calls and returns. The old 'set_args' etc names wouldn't really fit at that point, but then adding new opcodes for the new behavior is a clean deprecation path.