implements PR-06.3

This commit is contained in:
bQUARKz 2026-03-09 08:02:20 +00:00
parent bc98d5a3d4
commit 71d18d27c5
Signed by: bquarkz
SSH Key Fingerprint: SHA256:Z7dgqoglWwoK6j6u4QC87OveEq74WOhFN+gitsxtkf8
5 changed files with 135 additions and 2 deletions

View File

@ -39,8 +39,8 @@ to concrete positive/negative test evidence and current status.
| G19-5.2.6 | Gate S-I MUST reject missing capability at load-time. | N/A | `BackendGateIIntegrationTest#gateI_rejectMissingCapability` | pass | |
| G19-5.2.7 | Gate S-I MUST cover valid VM-owned intrinsic path. | `BackendGateIIntegrationTest#gateI_validIntrinsicPath` | N/A | pass | |
| G19-5.2.8 | Gate S-I MUST cover repeatability across runtime line. | `RuntimeBackedCompatibilityAdapterTest#checkMustPassInStrictModeWhenRuntimeCommandIsValid` | `RuntimeBackedCompatibilityAdapterTest#checkMustFailInStrictModeWhenRuntimeCommandIsUnavailable` | partial | Runtime-line repeatability is validated at adapter contract level; multi-line matrix coverage is pending. |
| G20-6.2 | `IRVM_EXT` MUST declare structural metadata (`pops/pushes/is_branch/is_terminator`). | `IRVMOp` contract (`INTERNAL_EXT` shape) | N/A | partial | Needs dedicated extension-op fixtures beyond `INTERNAL_EXT`. |
| G20-6.3 | `IRVM_EXT` MUST be eliminable before bytecode emission. | `OptimizeIRVMServiceTest#optimizeDefaultPassesMustRemoveUnreachableInstructions` | `EmitBytecodePipelineStageTest#runMustFailWhenInternalOpcodesRemain`; `IRVMValidatorTest#validateMustRejectInternalOpcodeWhenConfigured` | pass | Emit stage blocks residual internal opcodes. |
| G20-6.2 | `IRVM_EXT` MUST declare structural metadata (`pops/pushes/is_branch/is_terminator`). | `IRVMValidatorTest#validateMustApplyStructuralMetadataForCustomInternalExtension`; `IRVMValidatorTest#validateMustRejectCustomInternalExtensionWhenStructuralMetadataUnderflowsStack`; `IRVMOp` record contract (`pops/pushes/branch/terminator/internal`) | N/A | pass | Dedicated extension fixtures now assert structural metadata is consumed by validation behavior. |
| G20-6.3 | `IRVM_EXT` MUST be eliminable before bytecode emission. | `OptimizeIRVMServiceTest#optimizeDefaultPassesMustEliminateUnreachableInternalExtensionBeforeEmission` | `EmitBytecodePipelineStageTest#runMustFailWhenInternalOpcodesRemain`; `EmitBytecodePipelineStageTest#runMustFailWhenInternalOpcodesRemainEvenWithNonEmptyEmissionPlan`; `IRVMValidatorTest#validateMustRejectInternalOpcodeWhenConfigured` | pass | Optimizer elimination path and emit-stage hard rejection path are both covered. |
| G20-6.4 | IRVM MUST preserve per-function slot and identity headers. | `IRVMProgramTest#constructorMustRejectModuleAndEmissionPlanMismatch` | `IRVMProgramTest#constructorMustRejectModuleAndEmissionPlanMismatch` | pass | Header mismatch is rejected deterministically. |
| G20-7.2 | Jump immediates MUST resolve to u32 function-relative offsets before emission. | `LowerToIRVMServiceTest#lowerMustResolveJumpTargetsFromLabels`; `BytecodeEmitterTest#emitMustEncodeJumpOpcodesWithU32Immediate` | `LowerToIRVMServiceTest#lowerMustRejectMissingJumpTargetLabel` | pass | |
| G20-7.3 | Jump targets MUST be instruction-boundary valid. | N/A | `IRVMValidatorTest#validateMustRejectInvalidJumpTarget` | pass | |

View File

@ -85,6 +85,9 @@ public record IRVMProgram(
private boolean coherentPair(
final IRVMInstruction instruction,
final BytecodeEmitter.Operation operation) {
if (instruction.op().internal()) {
return true;
}
final var immediate = instruction.immediate() == null ? 0 : instruction.immediate();
return switch (instruction.op().opcode()) {
case 0x01 -> operation.kind() == BytecodeEmitter.OperationKind.HALT;

View File

@ -5,6 +5,9 @@ import p.studio.compiler.backend.bytecode.BytecodeEmitter;
import p.studio.compiler.backend.bytecode.BytecodeModule;
import p.studio.utilities.structures.ReadOnlyList;
import java.util.Map;
import java.util.Set;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertThrows;
@ -125,6 +128,49 @@ class IRVMValidatorTest {
assertDoesNotThrow(() -> validator.validate(module, false));
}
@Test
void validateMustApplyStructuralMetadataForCustomInternalExtension() {
final var extPush = new IRVMOp("IRVM_EXT_PUSH", 0xFFFE, 0, 0, 1, false, false, true);
final var customGate = new IRVMProfileFeatureGate(Map.of(
"experimental-structural-v1", Set.of(extPush, IRVMOp.HALT)));
final var customValidator = new IRVMValidator(customGate);
final var module = new IRVMModule(
"experimental-structural-v1",
ReadOnlyList.from(new IRVMFunction(
"main",
0,
0,
0,
1,
ReadOnlyList.from(
new IRVMInstruction(extPush, null),
new IRVMInstruction(IRVMOp.HALT, null)))));
assertDoesNotThrow(() -> customValidator.validate(module, false));
}
@Test
void validateMustRejectCustomInternalExtensionWhenStructuralMetadataUnderflowsStack() {
final var extPop = new IRVMOp("IRVM_EXT_POP", 0xFFFD, 0, 1, 0, false, false, true);
final var customGate = new IRVMProfileFeatureGate(Map.of(
"experimental-structural-v1", Set.of(extPop, IRVMOp.HALT)));
final var customValidator = new IRVMValidator(customGate);
final var module = new IRVMModule(
"experimental-structural-v1",
ReadOnlyList.from(new IRVMFunction(
"main",
0,
0,
0,
1,
ReadOnlyList.from(
new IRVMInstruction(extPop, null),
new IRVMInstruction(IRVMOp.HALT, null)))));
final var thrown = assertThrows(IRVMValidationException.class, () -> customValidator.validate(module, false));
assertEquals(IRVMValidationErrorCode.MARSHAL_VERIFY_PRECHECK_STACK_UNDERFLOW, thrown.code());
}
@Test
void validateProgramMustRejectIntrinsicWithoutSignatureMetadata() {
final var module = new IRVMModule(

View File

@ -2,12 +2,14 @@ package p.studio.compiler.backend.irvm;
import org.junit.jupiter.api.Test;
import p.studio.compiler.backend.bytecode.BytecodeEmitter;
import p.studio.compiler.backend.bytecode.BytecodePreloadVerifierService;
import p.studio.utilities.structures.ReadOnlyList;
import java.util.ArrayList;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
@ -127,6 +129,51 @@ class OptimizeIRVMServiceTest {
assertEquals(BytecodeEmitter.OperationKind.RET, optimized.emissionPlan().functions().getFirst().operations().getFirst().kind());
}
@Test
void optimizeDefaultPassesMustEliminateUnreachableInternalExtensionBeforeEmission() {
final var service = new OptimizeIRVMService();
final var input = new IRVMProgram(
new IRVMModule(
"experimental-v1",
ReadOnlyList.from(new IRVMFunction(
"main",
0,
0,
0,
1,
ReadOnlyList.from(
new IRVMInstruction(IRVMOp.JMP, 8),
new IRVMInstruction(IRVMOp.INTERNAL_EXT, null),
new IRVMInstruction(IRVMOp.RET, null))))),
new BytecodeEmitter.EmissionPlan(
0,
ReadOnlyList.empty(),
ReadOnlyList.empty(),
ReadOnlyList.from(new BytecodeEmitter.FunctionPlan(
"main",
0,
0,
0,
1,
ReadOnlyList.from(
BytecodeEmitter.Operation.jmp(8, null),
BytecodeEmitter.Operation.halt(),
BytecodeEmitter.Operation.ret())))));
final var optimized = service.optimize(input);
final var function = optimized.module().functions().getFirst();
final var firstInstruction = function.instructions().getFirst();
final var firstOperation = optimized.coherentEmissionPlan().functions().getFirst().operations().getFirst();
assertEquals(1, function.instructions().size());
assertFalse(optimized.hasInternalOpcodes());
assertEquals(IRVMOp.RET, firstInstruction.op());
assertEquals(BytecodeEmitter.OperationKind.RET, firstOperation.kind());
final var emitted = new BytecodeEmitter().emit(optimized.coherentEmissionPlan());
new BytecodePreloadVerifierService().verify(emitted);
}
private OptimizeIRVMService.IRVMPass namedPass(
final String name,
final List<String> order,

View File

@ -43,6 +43,43 @@ class EmitBytecodePipelineStageTest {
assertEquals("MARSHAL_VERIFY_PRECHECK_INTERNAL_OPCODE_RESIDUAL", firstIssue.getCode());
}
@Test
void runMustFailWhenInternalOpcodesRemainEvenWithNonEmptyEmissionPlan() {
final var ctx = BuilderPipelineContext.compilerContext(new BuilderPipelineConfig(false, "."));
ctx.optimizedIrvm = new IRVMProgram(
new p.studio.compiler.backend.irvm.IRVMModule(
"experimental-v1",
ReadOnlyList.from(new p.studio.compiler.backend.irvm.IRVMFunction(
"main",
0,
0,
0,
1,
ReadOnlyList.from(
new p.studio.compiler.backend.irvm.IRVMInstruction(p.studio.compiler.backend.irvm.IRVMOp.INTERNAL_EXT, null),
new p.studio.compiler.backend.irvm.IRVMInstruction(p.studio.compiler.backend.irvm.IRVMOp.RET, null))))),
new BytecodeEmitter.EmissionPlan(
0,
ReadOnlyList.empty(),
ReadOnlyList.empty(),
ReadOnlyList.from(new BytecodeEmitter.FunctionPlan(
"main",
0,
0,
0,
1,
ReadOnlyList.from(
BytecodeEmitter.Operation.halt(),
BytecodeEmitter.Operation.ret())))));
final var stage = new EmitBytecodePipelineStage();
final var issues = stage.run(ctx, LogAggregator.empty());
final var firstIssue = issues.asCollection().iterator().next();
assertTrue(issues.hasErrors());
assertEquals("MARSHAL_VERIFY_PRECHECK_INTERNAL_OPCODE_RESIDUAL", firstIssue.getCode());
}
@Test
void runMustEmitBytecodeWhenPreconditionsAreSatisfied() {
final var ctx = BuilderPipelineContext.compilerContext(new BuilderPipelineConfig(false, "."));