API: Automatic creattion of MuInstResNode
Problem
Currently instruction results are added to the instruction after the instruction is created.
Alternatively, results can be created when the instruction is created. When taking this approach, the client will never add the wrong number of results to any instructions.
In theory, the client knows everything the micro VM knows about the IR bundle, so it is always capable of adding the right number of results. Changing the API in the following way will let the micro VM provide slightly more help to the client, but should not affect the performance: the micro VM always has the required information.
Minimalism will be affected if more query API (finding the opcode/mnemonic of instructions, the instruction parameters, etc.) is added. The client builds the IR, and always has full information of the structure of the CFG. So the client is always capable of pretty-printing what it is going to build without using any of the Mu API functions. For convenience, however, query API could be provided at a higher level by client-side libraries, while the C-based API provides an efficient (rather than rich) tool to transfer the information from the client to the micro VM. For debug purpose, the reference implementation can now print the loaded bundle as text.
Proposed change
Replace the new_inst_res
API function:
MuInstResNode (*new_inst_res )(MuCtx *ctx, MuInstNode inst);
with these :
MuInstResNode (*get_inst_res)(MuCtx *ctx, MuInstNode inst, int index);
int (*get_num_res)(MuCtx *ctx, MuInstNode inst);
get_inst_res
will get the index-th result from an instruction. get_num_res
gets the number of results.
Other API functions do not need to be changed.
About the number of results
Can the number of results be determined when constructing the instruction?
Checklist ( instruction: numOfResults ) :
- binary ops: 1
- comparing: 1
- conversion: 1
- SELECT: 1
- BRANCH: 0
- BRANCH2: 0
- SWITCH: 0
- CALL: the number of results in the signature
- TAILCALL: 0
- RET: 0
- THROW: 0
- EXTRACTVALUE: 1
- INSERTVALUE: 1
- EXTRACTELEMENT: 1
- INSERTELEMENT: 1
- SHUFFLEVECTOR: 1
- NEW: 1
- NEWHYBRID: 1
- ALLOCA: 1
- ALLOCAHYBRID: 1
- GETIREF: 1
- GETFIELDIREF: 1
- GETELEMIREF: 1
- SHIFTIREF: 1
- GETVARPARTIREF 1
- LOAD: 1
- STORE: 0
- CMPXCHG: 2 (succ, oldVal)
- ATOMICRMW: 1
- FENCE: 0
- TRAP: as many as the length of the type parameters.
- WATCHPOINT: as many as the length of the type parameters.
- WPBRANCH: 0
- CCALL: the number of results in the signature. Same as CALL
- NEWTHREAD: 1
- SWAPSTACK:
- 0 if
KILL_OLD
- n if
RET_WITH<T1 T2 ... Tn>
- 0 if
- COMMINST: currently all comminsts have fixed number of return values.