implements PR-O3.3

This commit is contained in:
bQUARKz 2026-03-07 18:31:31 +00:00
parent 0df936e36f
commit a79a19cd4f
Signed by: bquarkz
SSH Key Fingerprint: SHA256:Z7dgqoglWwoK6j6u4QC87OveEq74WOhFN+gitsxtkf8
4 changed files with 99 additions and 3 deletions

View File

@ -0,0 +1,44 @@
package p.studio.compiler.backend.irvm;
import java.util.Map;
import java.util.Set;
public final class IRVMProfileFeatureGate {
private final Map<String, Set<IRVMOp>> allowedByProfile;
public IRVMProfileFeatureGate() {
this(Map.of(
"core-v1", Set.of(
IRVMOp.HALT,
IRVMOp.RET,
IRVMOp.CALL,
IRVMOp.JMP,
IRVMOp.JMP_IF_TRUE,
IRVMOp.JMP_IF_FALSE,
IRVMOp.HOSTCALL,
IRVMOp.INTRINSIC,
IRVMOp.PUSH_I32),
"experimental-v1", Set.of(
IRVMOp.HALT,
IRVMOp.RET,
IRVMOp.CALL,
IRVMOp.JMP,
IRVMOp.JMP_IF_TRUE,
IRVMOp.JMP_IF_FALSE,
IRVMOp.HOSTCALL,
IRVMOp.INTRINSIC,
IRVMOp.PUSH_I32,
IRVMOp.INTERNAL_EXT)));
}
IRVMProfileFeatureGate(final Map<String, Set<IRVMOp>> allowedByProfile) {
this.allowedByProfile = allowedByProfile == null ? Map.of() : Map.copyOf(allowedByProfile);
}
public boolean isAllowed(
final String profile,
final IRVMOp op) {
final var allowed = allowedByProfile.get(profile == null || profile.isBlank() ? "core-v1" : profile);
return allowed != null && allowed.contains(op);
}
}

View File

@ -9,5 +9,5 @@ public enum IRVMValidationErrorCode {
MARSHAL_VERIFY_PRECHECK_INVALID_FUNC_ID,
MARSHAL_VERIFY_PRECHECK_UNTERMINATED_PATH,
MARSHAL_VERIFY_PRECHECK_INTERNAL_OPCODE_RESIDUAL,
MARSHAL_VERIFY_PRECHECK_OPCODE_NOT_ALLOWED_FOR_PROFILE,
}

View File

@ -5,6 +5,15 @@ import java.util.HashMap;
import java.util.HashSet;
public class IRVMValidator {
private final IRVMProfileFeatureGate profileFeatureGate;
public IRVMValidator() {
this(new IRVMProfileFeatureGate());
}
IRVMValidator(final IRVMProfileFeatureGate profileFeatureGate) {
this.profileFeatureGate = profileFeatureGate;
}
public void validate(
final IRVMModule module,
@ -40,6 +49,13 @@ public class IRVMValidator {
functionIndex,
pcByIndex[i]);
}
if (!profileFeatureGate.isAllowed(module.vmProfile(), instr.op())) {
throw new IRVMValidationException(
IRVMValidationErrorCode.MARSHAL_VERIFY_PRECHECK_OPCODE_NOT_ALLOWED_FOR_PROFILE,
"opcode '%s' is not allowed for vm profile '%s'".formatted(instr.op().name(), module.vmProfile()),
functionIndex,
pcByIndex[i]);
}
}
final var worklist = new ArrayDeque<Integer>();
@ -222,4 +238,3 @@ public class IRVMValidator {
}
}
}

View File

@ -4,6 +4,7 @@ import org.junit.jupiter.api.Test;
import p.studio.utilities.structures.ReadOnlyList;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertThrows;
class IRVMValidatorTest {
@ -84,5 +85,41 @@ class IRVMValidatorTest {
final var thrown = assertThrows(IRVMValidationException.class, () -> validator.validate(module, true));
assertEquals(IRVMValidationErrorCode.MARSHAL_VERIFY_PRECHECK_INTERNAL_OPCODE_RESIDUAL, thrown.code());
}
}
@Test
void validateMustRejectOpcodeOutsideProfileFeatureGate() {
final var module = new IRVMModule(
"core-v1",
ReadOnlyList.from(
new IRVMFunction(
"main",
0,
0,
0,
1,
ReadOnlyList.from(
new IRVMInstruction(IRVMOp.INTERNAL_EXT, null),
new IRVMInstruction(IRVMOp.HALT, null)))));
final var thrown = assertThrows(IRVMValidationException.class, () -> validator.validate(module, false));
assertEquals(IRVMValidationErrorCode.MARSHAL_VERIFY_PRECHECK_OPCODE_NOT_ALLOWED_FOR_PROFILE, thrown.code());
}
@Test
void validateMayAllowProfileSpecificOpcodeWhenProfileSupportsIt() {
final var module = new IRVMModule(
"experimental-v1",
ReadOnlyList.from(
new IRVMFunction(
"main",
0,
0,
0,
1,
ReadOnlyList.from(
new IRVMInstruction(IRVMOp.INTERNAL_EXT, null),
new IRVMInstruction(IRVMOp.HALT, null)))));
assertDoesNotThrow(() -> validator.validate(module, false));
}
}