Class JitDataFlowUseropLibrary

java.lang.Object
ghidra.pcode.emu.jit.analysis.JitDataFlowUseropLibrary
All Implemented Interfaces:
PcodeUseropLibrary<JitVal>

public class JitDataFlowUseropLibrary extends Object implements PcodeUseropLibrary<JitVal>
A wrapper around a userop library that places callother ops into the use-def graph

This is the library provided to PcodeExecutor.execute(PcodeProgram, PcodeUseropLibrary) to cooperate with in the population of the use-def graph. The Sleigh compiler is very permissive when it comes to userop invocations. Notably, there's no way to declare the "prototype" or "signature" of the userop. Invocations can have any number of input operands and an optional output operand. Because the use-def graph takes careful notice of variables and their definiting ops, there are two possible op nodes: JitCallOtherOp when no output operand is given and JitCallOtherDefOp when an output operand is given.

We employ several different strategies to handle a p-code userop:

  • Standard: Invocation of the userop in the same fashion as the interpreted p-code emulator. Any live variables have to be written into the state before the invocation and the read back out afterward. If the userop accesses the state directly, we must use this strategy. Most userops whose implementations precede the introduction of JIT acceleration can be supported with this strategy, so long as they don't manipulate the emulator/executor directly is some unsupported way.
  • Inlining: The inclusion of the userop's p-code directly at its call site, replacing the PcodeOp.CALLOTHER op. This is implemented in the decoder by DecoderUseropLibrary. This strategy is only applicable to userops defined using Sleigh and/or p-code.
  • Direct: The direct invocation of the userop's defining Java method in the generated JVM bytecode. This is applicable when the method's parameters and return type are primitives that each map to a JitTypeBehavior. The input values can be passed directly in, which works well when the inputs are registers or uniques allocated in JVM locals. The return value can be handled similarly.

The default strategy for all userops is Standard. Implementors should set the attributes of AnnotatedPcodeUseropLibrary.PcodeUserop and adjust the parameters of the userop's method accordingly. To allow inlining, set canInline. To allow direct invocation, set AnnotatedPcodeUseropLibrary.PcodeUserop.functional() and ensure all the parameter types and return type are supported. Supported types include primitives other than char. The return type may be void. No matter the strategy, userops may be subject to removal by the JitOpUseModel. To permit removal, clear AnnotatedPcodeUseropLibrary.PcodeUserop.hasSideEffects(). The default prevents removal. For the inline strategy, each op from the inlined userop is analyzed separately, so the userop could be partially culled. An inlined userop cannot have side effects, and so the attribute is ignored.