// Copyright (c) StellaOps. All rights reserved.
// Licensed under AGPL-3.0-or-later. See LICENSE in the project root.
using System.Collections.Immutable;
namespace StellaOps.BinaryIndex.Semantic;
///
/// A function lifted to intermediate representation.
///
/// Function name (may be empty for unnamed functions).
/// Start address of the function.
/// IR statements comprising the function body.
/// Basic blocks in the function.
/// Control flow graph.
public sealed record LiftedFunction(
string Name,
ulong Address,
ImmutableArray Statements,
ImmutableArray BasicBlocks,
ControlFlowGraph Cfg);
///
/// A function transformed to Static Single Assignment (SSA) form.
///
/// Function name.
/// Start address of the function.
/// SSA statements comprising the function body.
/// SSA basic blocks in the function.
/// Definition-use chains for dataflow analysis.
public sealed record SsaFunction(
string Name,
ulong Address,
ImmutableArray Statements,
ImmutableArray BasicBlocks,
DefUseChains DefUse);
///
/// An intermediate representation statement.
///
/// Unique statement ID within the function.
/// Original instruction address.
/// Statement kind.
/// Operation name (e.g., add, sub, load).
/// Destination operand (if any).
/// Source operands.
/// Additional metadata.
public sealed record IrStatement(
int Id,
ulong Address,
IrStatementKind Kind,
string Operation,
IrOperand? Destination,
ImmutableArray Sources,
ImmutableDictionary? Metadata = null);
///
/// Kind of IR statement.
///
public enum IrStatementKind
{
/// Unknown statement kind.
Unknown = 0,
/// Assignment: dest = expr.
Assign,
/// Binary operation: dest = src1 op src2.
BinaryOp,
/// Unary operation: dest = op src.
UnaryOp,
/// Memory load: dest = [addr].
Load,
/// Memory store: [addr] = src.
Store,
/// Unconditional jump.
Jump,
/// Conditional jump.
ConditionalJump,
/// Function call.
Call,
/// Function return.
Return,
/// No operation.
Nop,
/// PHI node (for SSA form).
Phi,
/// System call.
Syscall,
/// Interrupt.
Interrupt,
/// Cast/type conversion.
Cast,
/// Comparison.
Compare,
/// Sign/zero extension.
Extend
}
///
/// An operand in an IR statement.
///
/// Operand kind.
/// Name (for temporaries and registers).
/// Constant value (for immediates).
/// Size in bits.
/// Whether this is a memory reference.
public sealed record IrOperand(
IrOperandKind Kind,
string? Name,
long? Value,
int BitSize,
bool IsMemory = false);
///
/// Kind of IR operand.
///
public enum IrOperandKind
{
/// Unknown operand kind.
Unknown = 0,
/// CPU register.
Register,
/// IR temporary variable.
Temporary,
/// Immediate constant value.
Immediate,
/// Memory address.
Memory,
/// Program counter / instruction pointer.
ProgramCounter,
/// Stack pointer.
StackPointer,
/// Base pointer / frame pointer.
FramePointer,
/// Flags/condition register.
Flags,
/// Undefined value (for SSA).
Undefined,
/// Label / address reference.
Label
}
///
/// A basic block in the intermediate representation.
///
/// Unique block ID within the function.
/// Block label/name.
/// Start address of the block.
/// End address of the block (exclusive).
/// IDs of statements in this block.
/// IDs of predecessor blocks.
/// IDs of successor blocks.
public sealed record IrBasicBlock(
int Id,
string Label,
ulong StartAddress,
ulong EndAddress,
ImmutableArray StatementIds,
ImmutableArray Predecessors,
ImmutableArray Successors);
///
/// Control flow graph for a function.
///
/// ID of the entry block.
/// IDs of exit blocks.
/// CFG edges.
public sealed record ControlFlowGraph(
int EntryBlockId,
ImmutableArray ExitBlockIds,
ImmutableArray Edges);
///
/// An edge in the control flow graph.
///
/// Source block ID.
/// Target block ID.
/// Edge kind.
/// Condition for conditional edges.
public sealed record CfgEdge(
int SourceBlockId,
int TargetBlockId,
CfgEdgeKind Kind,
string? Condition = null);
///
/// Kind of CFG edge.
///
public enum CfgEdgeKind
{
/// Sequential fall-through.
FallThrough,
/// Unconditional jump.
Jump,
/// Conditional branch taken.
ConditionalTrue,
/// Conditional branch not taken.
ConditionalFalse,
/// Function call edge.
Call,
/// Function return edge.
Return,
/// Indirect jump (computed target).
Indirect,
/// Exception/interrupt edge.
Exception
}
///
/// An SSA statement with versioned variables.
///
/// Unique statement ID within the function.
/// Original instruction address.
/// Statement kind.
/// Operation name.
/// Destination SSA variable (if any).
/// Source SSA variables.
/// For PHI nodes: mapping from predecessor block to variable version.
public sealed record SsaStatement(
int Id,
ulong Address,
IrStatementKind Kind,
string Operation,
SsaVariable? Destination,
ImmutableArray Sources,
ImmutableDictionary? PhiSources = null);
///
/// An SSA variable (versioned).
///
/// Original variable/register name.
/// SSA version number.
/// Size in bits.
/// Variable kind.
public sealed record SsaVariable(
string BaseName,
int Version,
int BitSize,
SsaVariableKind Kind);
///
/// Kind of SSA variable.
///
public enum SsaVariableKind
{
/// CPU register.
Register,
/// IR temporary.
Temporary,
/// Memory location.
Memory,
/// Immediate constant.
Constant,
/// PHI result.
Phi
}
///
/// An SSA basic block.
///
/// Unique block ID.
/// Block label.
/// PHI nodes at block entry.
/// Non-PHI statements.
/// Predecessor block IDs.
/// Successor block IDs.
public sealed record SsaBasicBlock(
int Id,
string Label,
ImmutableArray PhiNodes,
ImmutableArray Statements,
ImmutableArray Predecessors,
ImmutableArray Successors);
///
/// Definition-use chains for SSA form.
///
/// Maps variable to its defining statement.
/// Maps variable to statements that use it.
public sealed record DefUseChains(
ImmutableDictionary Definitions,
ImmutableDictionary> Uses);