Package ghidra.pcode.emu.jit.analysis

# 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.

- ## Nested Class Summary

  Nested Classes
  Modifier and Type
  Class
  Description
  `protected class`
  `JitDataFlowUseropLibrary.WrappedUseropDefinition`
  The wrapper of a specific userop definition

  ## Nested classes/interfaces inherited from interface ghidra.pcode.exec.PcodeUseropLibrary

  `PcodeUseropLibrary.EmptyPcodeUseropLibrary, PcodeUseropLibrary.PcodeUseropDefinition<T>`

- ## Field Summary

  ### Fields inherited from interface ghidra.pcode.exec.PcodeUseropLibrary

  `NIL`

- ## Constructor Summary

  Constructors
  Constructor
  Description
  `JitDataFlowUseropLibrary(JitAnalysisContext context, JitDataFlowModel dfm)`
  Construct a wrapper library

- ## Method Summary

  Modifier and Type
  Method
  Description
  `Map<String,PcodeUseropLibrary.PcodeUseropDefinition<JitVal>>`
  `getUserops()`
  Get all the userops defined in this library, keyed by (symbol) name.

  ### Methods inherited from class java.lang.Object

  `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

  ### Methods inherited from interface ghidra.pcode.exec.PcodeUseropLibrary

  `compose, getSymbols`

- ## Constructor Details

  - ### JitDataFlowUseropLibrary

    public JitDataFlowUseropLibrary(JitAnalysisContext context, JitDataFlowModel dfm)
    Construct a wrapper library
    Parameters:
      `context` - the context from which the decoder's userop wrapper library is retrieved
      `dfm` - the data flow model whose use-def graph to populate.
    Implementation Notes:
      Each time this is constructed, it has to traverse the wrapped userop library and create a wrapper for each individual userop. For a large library, this could get expensive, and it currently must happen for every passage compiled. Part of the cause for this requirement is the reference to the data flow mode used by each userop wrapper.

- ## Method Details

  - ### getUserops

    public Map<String,PcodeUseropLibrary.PcodeUseropDefinition<JitVal>> getUserops()
    Description copied from interface: `PcodeUseropLibrary`
    Get all the userops defined in this library, keyed by (symbol) name.
    Specified by:
      `getUserops` in interface `PcodeUseropLibrary<JitVal>`
    Returns:
      the map of names to defined userops