Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,29 @@

## [Unreleased]

### Changed

- **StableHLO conversion fails loudly by default**
([#1247](https://github.com/SKaiNET-developers/SKaiNET/issues/1247)): converter failures were
MLIR comments — a graph whose first node failed to lower could cascade through every downstream
node and still "succeed" with an empty `return` and exit 0. `StableHloConverter` and every
`StableHloConverterFactory` entry point now take a `ConversionErrorPolicy` (default `STRICT`):
an unconvertible node throws `HloConversionException`, and an operand whose producer was never
converted throws `MissingOperandException` instead of being silently dropped and shifting later
operands into earlier positions. `ConversionErrorPolicy.LENIENT` restores the historical
comment-and-continue behavior for callers that inspect partially-converted modules.

### Fixed

- **`indexSelect` is now routable in the StableHLO gather converter**
([#1247](https://github.com/SKaiNET-developers/SKaiNET/issues/1247)): the KSP tracing wrapper
emits `indexSelect`, but the registry only knew `index_select`, so traced index-select nodes
(e.g. Gemma per-layer embeddings) could not lower. Both spellings route to the gather lowering.
- **`StableHloConverterFactory.createBasic` registers `NeuralNetOperationsConverter`**
([#1247](https://github.com/SKaiNET-developers/SKaiNET/issues/1247)): parity with
`createExtended` — a traced model with conv/pool/norm nodes no longer fails to lower via the
basic factory, with registration order preserving existing op-name precedence.

## [0.52.0] - 2026-09-01

Headline: **the engine stops silently running on the scalar floor.** A downstream Gemma 4 port
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,16 @@ public final class sk/ainet/compile/hlo/ConversionContext {
public fun <init> (Lsk/ainet/compile/hlo/TypeMapper;Lsk/ainet/lang/graph/ComputeGraph;Lsk/ainet/compile/hlo/ConstantMaterializationPolicy;)V
public fun <init> (Lsk/ainet/compile/hlo/TypeMapper;Lsk/ainet/lang/graph/ComputeGraph;Lsk/ainet/compile/hlo/ConstantMaterializationPolicy;Ljava/lang/String;)V
public fun <init> (Lsk/ainet/compile/hlo/TypeMapper;Lsk/ainet/lang/graph/ComputeGraph;Lsk/ainet/compile/hlo/ConstantMaterializationPolicy;Ljava/lang/String;Lsk/ainet/compile/target/OpGranularityPolicy;)V
public synthetic fun <init> (Lsk/ainet/compile/hlo/TypeMapper;Lsk/ainet/lang/graph/ComputeGraph;Lsk/ainet/compile/hlo/ConstantMaterializationPolicy;Ljava/lang/String;Lsk/ainet/compile/target/OpGranularityPolicy;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Lsk/ainet/compile/hlo/TypeMapper;Lsk/ainet/lang/graph/ComputeGraph;Lsk/ainet/compile/hlo/ConstantMaterializationPolicy;Ljava/lang/String;Lsk/ainet/compile/target/OpGranularityPolicy;Lsk/ainet/compile/hlo/ConversionErrorPolicy;)V
public synthetic fun <init> (Lsk/ainet/compile/hlo/TypeMapper;Lsk/ainet/lang/graph/ComputeGraph;Lsk/ainet/compile/hlo/ConstantMaterializationPolicy;Ljava/lang/String;Lsk/ainet/compile/target/OpGranularityPolicy;Lsk/ainet/compile/hlo/ConversionErrorPolicy;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun clear ()V
public final fun emitComment (Ljava/lang/String;)V
public final fun emitEncodingAnnotation (Ljava/lang/String;ILsk/ainet/lang/tensor/ops/TensorSpec;)V
public final fun emitLine (Ljava/lang/String;)V
public final fun emitModuleDeclaration (Ljava/lang/String;)V
public final fun emitOperation (Ljava/lang/String;)V
public final fun getContent ()Ljava/lang/String;
public final fun getErrorPolicy ()Lsk/ainet/compile/hlo/ConversionErrorPolicy;
public final fun getExternalParameters ()Ljava/util/List;
public final fun getGranularity ()Lsk/ainet/compile/target/OpGranularityPolicy;
public final fun getInputNodes (Lsk/ainet/lang/graph/GraphNode;)Ljava/util/List;
Expand All @@ -74,6 +76,14 @@ public final class sk/ainet/compile/hlo/ConversionContext {
public final fun setValueType (Ljava/lang/String;Ljava/lang/String;)V
}

public final class sk/ainet/compile/hlo/ConversionErrorPolicy : java/lang/Enum {
public static final field LENIENT Lsk/ainet/compile/hlo/ConversionErrorPolicy;
public static final field STRICT Lsk/ainet/compile/hlo/ConversionErrorPolicy;
public static fun getEntries ()Lkotlin/enums/EnumEntries;
public static fun valueOf (Ljava/lang/String;)Lsk/ainet/compile/hlo/ConversionErrorPolicy;
public static fun values ()[Lsk/ainet/compile/hlo/ConversionErrorPolicy;
}

public abstract class sk/ainet/compile/hlo/ConversionResult {
}

Expand Down Expand Up @@ -153,6 +163,20 @@ public final class sk/ainet/compile/hlo/ExternalParameterRef {
public fun toString ()Ljava/lang/String;
}

public final class sk/ainet/compile/hlo/HloConversionException : java/lang/IllegalStateException {
public fun <init> (Ljava/lang/String;Ljava/lang/Throwable;)V
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/Throwable;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
}

public final class sk/ainet/compile/hlo/MissingOperandException : java/lang/IllegalStateException {
public fun <init> (Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;I)V
public final fun getInputPort ()I
public final fun getNodeId ()Ljava/lang/String;
public final fun getOpName ()Ljava/lang/String;
public final fun getSourceNodeId ()Ljava/lang/String;
public final fun getSourceOutputPort ()I
}

public final class sk/ainet/compile/hlo/MlirValidator {
public fun <init> ()V
public final fun validate (Ljava/lang/String;)Ljava/util/List;
Expand Down Expand Up @@ -189,7 +213,8 @@ public final class sk/ainet/compile/hlo/StableHloConverter {
public fun <init> (Lsk/ainet/compile/hlo/StableHloOperationRegistry;Lsk/ainet/compile/hlo/TypeMapper;Lsk/ainet/compile/hlo/MlirValidator;Lsk/ainet/compile/hlo/ConstantMaterializationPolicy;)V
public fun <init> (Lsk/ainet/compile/hlo/StableHloOperationRegistry;Lsk/ainet/compile/hlo/TypeMapper;Lsk/ainet/compile/hlo/MlirValidator;Lsk/ainet/compile/hlo/ConstantMaterializationPolicy;Ljava/lang/String;)V
public fun <init> (Lsk/ainet/compile/hlo/StableHloOperationRegistry;Lsk/ainet/compile/hlo/TypeMapper;Lsk/ainet/compile/hlo/MlirValidator;Lsk/ainet/compile/hlo/ConstantMaterializationPolicy;Ljava/lang/String;Lsk/ainet/compile/target/OpGranularityPolicy;)V
public synthetic fun <init> (Lsk/ainet/compile/hlo/StableHloOperationRegistry;Lsk/ainet/compile/hlo/TypeMapper;Lsk/ainet/compile/hlo/MlirValidator;Lsk/ainet/compile/hlo/ConstantMaterializationPolicy;Ljava/lang/String;Lsk/ainet/compile/target/OpGranularityPolicy;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Lsk/ainet/compile/hlo/StableHloOperationRegistry;Lsk/ainet/compile/hlo/TypeMapper;Lsk/ainet/compile/hlo/MlirValidator;Lsk/ainet/compile/hlo/ConstantMaterializationPolicy;Ljava/lang/String;Lsk/ainet/compile/target/OpGranularityPolicy;Lsk/ainet/compile/hlo/ConversionErrorPolicy;)V
public synthetic fun <init> (Lsk/ainet/compile/hlo/StableHloOperationRegistry;Lsk/ainet/compile/hlo/TypeMapper;Lsk/ainet/compile/hlo/MlirValidator;Lsk/ainet/compile/hlo/ConstantMaterializationPolicy;Ljava/lang/String;Lsk/ainet/compile/target/OpGranularityPolicy;Lsk/ainet/compile/hlo/ConversionErrorPolicy;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun convert (Lsk/ainet/lang/graph/ComputeGraph;Ljava/lang/String;)Lsk/ainet/compile/hlo/StableHloModule;
public static synthetic fun convert$default (Lsk/ainet/compile/hlo/StableHloConverter;Lsk/ainet/lang/graph/ComputeGraph;Ljava/lang/String;ILjava/lang/Object;)Lsk/ainet/compile/hlo/StableHloModule;
public final fun convertWithOptimization (Lsk/ainet/lang/graph/ComputeGraph;Lsk/ainet/compile/hlo/StableHloOptimizer;)Lsk/ainet/compile/hlo/StableHloModule;
Expand All @@ -201,18 +226,22 @@ public final class sk/ainet/compile/hlo/StableHloConverterFactory {
public static final fun createBasic (Lsk/ainet/compile/hlo/ConstantMaterializationPolicy;)Lsk/ainet/compile/hlo/StableHloConverter;
public static final fun createBasic (Lsk/ainet/compile/hlo/ConstantMaterializationPolicy;Ljava/lang/String;)Lsk/ainet/compile/hlo/StableHloConverter;
public static final fun createBasic (Lsk/ainet/compile/hlo/ConstantMaterializationPolicy;Ljava/lang/String;Lsk/ainet/compile/target/OpGranularityPolicy;)Lsk/ainet/compile/hlo/StableHloConverter;
public static synthetic fun createBasic$default (Lsk/ainet/compile/hlo/ConstantMaterializationPolicy;Ljava/lang/String;Lsk/ainet/compile/target/OpGranularityPolicy;ILjava/lang/Object;)Lsk/ainet/compile/hlo/StableHloConverter;
public static final fun createBasic (Lsk/ainet/compile/hlo/ConstantMaterializationPolicy;Ljava/lang/String;Lsk/ainet/compile/target/OpGranularityPolicy;Lsk/ainet/compile/hlo/ConversionErrorPolicy;)Lsk/ainet/compile/hlo/StableHloConverter;
public static synthetic fun createBasic$default (Lsk/ainet/compile/hlo/ConstantMaterializationPolicy;Ljava/lang/String;Lsk/ainet/compile/target/OpGranularityPolicy;Lsk/ainet/compile/hlo/ConversionErrorPolicy;ILjava/lang/Object;)Lsk/ainet/compile/hlo/StableHloConverter;
public static final fun createCustom (Lsk/ainet/compile/hlo/StableHloOperationRegistry;)Lsk/ainet/compile/hlo/StableHloConverter;
public static final fun createCustom (Lsk/ainet/compile/hlo/StableHloOperationRegistry;Lsk/ainet/compile/hlo/TypeMapper;)Lsk/ainet/compile/hlo/StableHloConverter;
public static final fun createCustom (Lsk/ainet/compile/hlo/StableHloOperationRegistry;Lsk/ainet/compile/hlo/TypeMapper;Lsk/ainet/compile/hlo/MlirValidator;)Lsk/ainet/compile/hlo/StableHloConverter;
public static final fun createCustom (Lsk/ainet/compile/hlo/StableHloOperationRegistry;Lsk/ainet/compile/hlo/TypeMapper;Lsk/ainet/compile/hlo/MlirValidator;Lsk/ainet/compile/hlo/ConstantMaterializationPolicy;)Lsk/ainet/compile/hlo/StableHloConverter;
public static synthetic fun createCustom$default (Lsk/ainet/compile/hlo/StableHloOperationRegistry;Lsk/ainet/compile/hlo/TypeMapper;Lsk/ainet/compile/hlo/MlirValidator;Lsk/ainet/compile/hlo/ConstantMaterializationPolicy;ILjava/lang/Object;)Lsk/ainet/compile/hlo/StableHloConverter;
public static final fun createCustom (Lsk/ainet/compile/hlo/StableHloOperationRegistry;Lsk/ainet/compile/hlo/TypeMapper;Lsk/ainet/compile/hlo/MlirValidator;Lsk/ainet/compile/hlo/ConstantMaterializationPolicy;Lsk/ainet/compile/hlo/ConversionErrorPolicy;)Lsk/ainet/compile/hlo/StableHloConverter;
public static synthetic fun createCustom$default (Lsk/ainet/compile/hlo/StableHloOperationRegistry;Lsk/ainet/compile/hlo/TypeMapper;Lsk/ainet/compile/hlo/MlirValidator;Lsk/ainet/compile/hlo/ConstantMaterializationPolicy;Lsk/ainet/compile/hlo/ConversionErrorPolicy;ILjava/lang/Object;)Lsk/ainet/compile/hlo/StableHloConverter;
public static final fun createExtended ()Lsk/ainet/compile/hlo/StableHloConverter;
public static final fun createExtended (Lsk/ainet/compile/hlo/ConstantMaterializationPolicy;)Lsk/ainet/compile/hlo/StableHloConverter;
public static synthetic fun createExtended$default (Lsk/ainet/compile/hlo/ConstantMaterializationPolicy;ILjava/lang/Object;)Lsk/ainet/compile/hlo/StableHloConverter;
public static final fun createExtended (Lsk/ainet/compile/hlo/ConstantMaterializationPolicy;Lsk/ainet/compile/hlo/ConversionErrorPolicy;)Lsk/ainet/compile/hlo/StableHloConverter;
public static synthetic fun createExtended$default (Lsk/ainet/compile/hlo/ConstantMaterializationPolicy;Lsk/ainet/compile/hlo/ConversionErrorPolicy;ILjava/lang/Object;)Lsk/ainet/compile/hlo/StableHloConverter;
public static final fun createFast ()Lsk/ainet/compile/hlo/StableHloConverter;
public static final fun createFast (Lsk/ainet/compile/hlo/ConstantMaterializationPolicy;)Lsk/ainet/compile/hlo/StableHloConverter;
public static synthetic fun createFast$default (Lsk/ainet/compile/hlo/ConstantMaterializationPolicy;ILjava/lang/Object;)Lsk/ainet/compile/hlo/StableHloConverter;
public static final fun createFast (Lsk/ainet/compile/hlo/ConstantMaterializationPolicy;Lsk/ainet/compile/hlo/ConversionErrorPolicy;)Lsk/ainet/compile/hlo/StableHloConverter;
public static synthetic fun createFast$default (Lsk/ainet/compile/hlo/ConstantMaterializationPolicy;Lsk/ainet/compile/hlo/ConversionErrorPolicy;ILjava/lang/Object;)Lsk/ainet/compile/hlo/StableHloConverter;
}

public final class sk/ainet/compile/hlo/StableHloExportArchitecture {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,13 @@ public class ConversionContext @kotlin.jvm.JvmOverloads constructor(
* caller from the [sk.ainet.compile.opt.TargetOptimizers] registry and passed in;
* `null` = decompose everything (portable default). The emitter only *reads* it.
*/
public val granularity: sk.ainet.compile.target.OpGranularityPolicy? = null
public val granularity: sk.ainet.compile.target.OpGranularityPolicy? = null,
/**
* How operand-resolution failures behave: [ConversionErrorPolicy.STRICT]
* (default) throws [MissingOperandException]; [ConversionErrorPolicy.LENIENT]
* reproduces the historical silent-drop (see issue #1247).
*/
public val errorPolicy: ConversionErrorPolicy = ConversionErrorPolicy.STRICT
) {
private val valueNames = mutableMapOf<String, String>()
private val valueTypes = mutableMapOf<String, String>()
Expand Down Expand Up @@ -78,10 +84,24 @@ public class ConversionContext @kotlin.jvm.JvmOverloads constructor(
*/
public fun resolveOperands(node: GraphNode): List<String> {
val g = graph ?: return emptyList()
return g.edges
val incoming = g.edges
.filter { it.destination.id == node.id }
.sortedBy { it.destinationInputIndex }
.mapNotNull { getValueName(it.source.id, it.sourceOutputIndex) }
if (errorPolicy == ConversionErrorPolicy.LENIENT) {
// Historical behavior: unresolved operands are dropped, and later
// operands slide into earlier positional slots (issue #1247).
return incoming.mapNotNull { getValueName(it.source.id, it.sourceOutputIndex) }
}
return incoming.map { edge ->
getValueName(edge.source.id, edge.sourceOutputIndex)
?: throw MissingOperandException(
nodeId = node.id,
opName = node.operation.name,
inputPort = edge.destinationInputIndex,
sourceNodeId = edge.source.id,
sourceOutputPort = edge.sourceOutputIndex,
)
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package sk.ainet.compile.hlo

/**
* Governs how the converter reacts when a node cannot be lowered.
*
* Historically every failure was emitted as an MLIR comment and conversion
* continued, so a broken graph could produce a compute-free module that
* still "succeeded" (empty `return`, exit 0) — see issue #1247, where an
* operand-linkage failure at the first node cascaded through 1000+ nodes
* silently. [STRICT] makes any conversion failure a thrown exception;
* [LENIENT] preserves the historical comment-and-continue behavior for
* callers that diff or inspect partially-converted modules.
*/
public enum class ConversionErrorPolicy {
/** Any node that fails to convert aborts the conversion with an exception. Default. */
STRICT,

/** Failures become MLIR comments and conversion continues (pre-#1247 behavior). */
LENIENT,
}

/**
* A node's input operand could not be resolved to an SSA value — its
* producer was never converted (or was converted under a different name).
*
* Thrown by [ConversionContext.resolveOperands] under
* [ConversionErrorPolicy.STRICT] instead of silently dropping the operand,
* which both hid the failure and shifted later operands into earlier
* positional slots (issue #1247: a gather whose weight operand failed saw
* its indices operand slide into slot 0).
*/
public class MissingOperandException(
public val nodeId: String,
public val opName: String,
public val inputPort: Int,
public val sourceNodeId: String,
public val sourceOutputPort: Int,
) : IllegalStateException(
"Node '$nodeId' (op '$opName') has no SSA value for input port $inputPort: " +
"producer node '$sourceNodeId' (output port $sourceOutputPort) was never " +
"successfully converted. Under ConversionErrorPolicy.LENIENT this operand " +
"would be silently dropped, shifting later operands into earlier slots."
)

/**
* A node failed to lower to StableHLO under [ConversionErrorPolicy.STRICT].
* Carries the same diagnostic text the LENIENT mode would have emitted as
* an MLIR comment, plus the causing exception when one was thrown.
*/
public class HloConversionException(
message: String,
cause: Throwable? = null,
) : IllegalStateException(message, cause)
Loading
Loading