These functions are almost entirely useless or incorrect; optimization
is better handled with the new pass manager, and the SysV ABI
transformation was incomplete and buggy.
As the difference between the PC value during lifting and execution must
be known, it is possible to use absolute value relocations to avoid
dynamic computations of addresses.
It is more reliable to encode an instruction and decode it again using
ll_func_decode_instr, especially given that Fadec does not give any
guarantees on ABI compatibility.
This adds two new configuration options: a function to use for tail
continuations and a function to use for function calls.
When a tail continuation function is specified, the exit block does not
return but performs a `musttail` call to that function. Tail
continuation is only performed once in the exit block.
When a call function is given, a CALL instruction will generate a call
to that function (setting RIP accordingly). The CFG decoder will assume
that the function is likely to return and continue decoding after a CALL
instruction. However, it will verify that the RIP matches and otherwise
return/tail continue. When CALL is lifted to an LLVM-IR call, a RET will
be forcefully lifted as LLVM-IR return, regardless of whether tail
continuation is enabled. This may lead to multiple returns in addition
to the single exit block.
This allows a user-specified function to be called as instruction
marker. Further, this change makes markers much more usable: they get
the current instruction pointer and the decoded FdInstr string as
metadata.
This removes the previous workaround to set specific registers even if
the SYSCALL implementation was overriden. Now there is a special
function override dedicated to only provide syscall semantics, but is
not required to set RCX and R11 as mandated by the ISA.
Register sizes are either encoded in operand sizes or overridden via
facets. There is no need to carry redundant information.
Note: This change BREAKS API AND ABI.
Note #2: It is probably easier not expose the instruction structs.
The operand representation of registers allows multiple representations
to map the same register in a non-obvious way. For the register file,
use a new, stripped down representation containing only the registers
which are actually contained in the register file.