diff --git a/prometeu-compiler/prometeu-build-pipeline/src/main/java/p/studio/compiler/backend/irvm/IRVMProfileFeatureGate.java b/prometeu-compiler/prometeu-build-pipeline/src/main/java/p/studio/compiler/backend/irvm/IRVMProfileFeatureGate.java index a812e471..01e8ddf7 100644 --- a/prometeu-compiler/prometeu-build-pipeline/src/main/java/p/studio/compiler/backend/irvm/IRVMProfileFeatureGate.java +++ b/prometeu-compiler/prometeu-build-pipeline/src/main/java/p/studio/compiler/backend/irvm/IRVMProfileFeatureGate.java @@ -35,10 +35,18 @@ public final class IRVMProfileFeatureGate { this.allowedByProfile = allowedByProfile == null ? Map.of() : Map.copyOf(allowedByProfile); } + public String normalizeProfile(final String profile) { + return profile == null || profile.isBlank() ? "core-v1" : profile; + } + + public boolean isSupportedProfile(final String profile) { + return allowedByProfile.containsKey(normalizeProfile(profile)); + } + public boolean isAllowed( final String profile, final IRVMOp op) { - final var allowed = allowedByProfile.get(profile == null || profile.isBlank() ? "core-v1" : profile); + final var allowed = allowedByProfile.get(normalizeProfile(profile)); return allowed != null && allowed.contains(op); } } diff --git a/prometeu-compiler/prometeu-build-pipeline/src/main/java/p/studio/compiler/backend/irvm/LowerToIRVMService.java b/prometeu-compiler/prometeu-build-pipeline/src/main/java/p/studio/compiler/backend/irvm/LowerToIRVMService.java index 1c28b39a..8cf1abb2 100644 --- a/prometeu-compiler/prometeu-build-pipeline/src/main/java/p/studio/compiler/backend/irvm/LowerToIRVMService.java +++ b/prometeu-compiler/prometeu-build-pipeline/src/main/java/p/studio/compiler/backend/irvm/LowerToIRVMService.java @@ -29,6 +29,12 @@ public class LowerToIRVMService { } public IRVMProgram lower(final IRBackend backend) { + return lower(backend, "core-v1"); + } + + public IRVMProgram lower( + final IRBackend backend, + final String vmProfile) { if (backend == null || backend.getExecutableFunctions().isEmpty()) { throw new IRVMLoweringException( IRVMLoweringErrorCode.LOWER_IRVM_EMPTY_EXECUTABLE_INPUT, @@ -194,7 +200,7 @@ public class LowerToIRVMService { ReadOnlyList.wrap(operations))); } - final var module = new IRVMModule("core-v1", ReadOnlyList.wrap(loweredFunctions)); + final var module = new IRVMModule(vmProfile, ReadOnlyList.wrap(loweredFunctions)); validator.validate(module, false); return new IRVMProgram( module, diff --git a/prometeu-compiler/prometeu-build-pipeline/src/main/java/p/studio/compiler/backend/irvm/OptimizeIRVMService.java b/prometeu-compiler/prometeu-build-pipeline/src/main/java/p/studio/compiler/backend/irvm/OptimizeIRVMService.java index a1c32d3a..d4aae29d 100644 --- a/prometeu-compiler/prometeu-build-pipeline/src/main/java/p/studio/compiler/backend/irvm/OptimizeIRVMService.java +++ b/prometeu-compiler/prometeu-build-pipeline/src/main/java/p/studio/compiler/backend/irvm/OptimizeIRVMService.java @@ -5,26 +5,35 @@ import java.util.Objects; public class OptimizeIRVMService { private final IRVMValidator validator; + private final IRVMProfileFeatureGate profileFeatureGate; private final List passes; public OptimizeIRVMService() { - this(new IRVMValidator(), List.of(new NoOpPass())); + this(new IRVMValidator(), new IRVMProfileFeatureGate(), List.of(new NoOpPass())); } OptimizeIRVMService(final IRVMValidator validator) { - this(validator, List.of(new NoOpPass())); + this(validator, new IRVMProfileFeatureGate(), List.of(new NoOpPass())); } OptimizeIRVMService( final IRVMValidator validator, final List passes) { + this(validator, new IRVMProfileFeatureGate(), passes); + } + + OptimizeIRVMService( + final IRVMValidator validator, + final IRVMProfileFeatureGate profileFeatureGate, + final List passes) { this.validator = validator; + this.profileFeatureGate = profileFeatureGate; this.passes = passes == null ? List.of(new NoOpPass()) : List.copyOf(passes); } public IRVMProgram optimize(final IRVMProgram input) { final var program = input == null ? IRVMProgram.empty() : input; - if (!"core-v1".equals(program.module().vmProfile())) { + if (!profileFeatureGate.isSupportedProfile(program.module().vmProfile())) { throw new IllegalArgumentException("unsupported vm profile: " + program.module().vmProfile()); } var current = program; diff --git a/prometeu-compiler/prometeu-build-pipeline/src/main/java/p/studio/compiler/messages/BuilderPipelineConfig.java b/prometeu-compiler/prometeu-build-pipeline/src/main/java/p/studio/compiler/messages/BuilderPipelineConfig.java index 5f871cbb..ff3a045b 100644 --- a/prometeu-compiler/prometeu-build-pipeline/src/main/java/p/studio/compiler/messages/BuilderPipelineConfig.java +++ b/prometeu-compiler/prometeu-build-pipeline/src/main/java/p/studio/compiler/messages/BuilderPipelineConfig.java @@ -2,4 +2,16 @@ package p.studio.compiler.messages; public record BuilderPipelineConfig( boolean explain, - String rootProjectPath) {} + String rootProjectPath, + String vmProfile) { + + public BuilderPipelineConfig( + final boolean explain, + final String rootProjectPath) { + this(explain, rootProjectPath, "core-v1"); + } + + public BuilderPipelineConfig { + vmProfile = vmProfile == null || vmProfile.isBlank() ? "core-v1" : vmProfile; + } +} diff --git a/prometeu-compiler/prometeu-build-pipeline/src/main/java/p/studio/compiler/workspaces/stages/LowerToIRVMPipelineStage.java b/prometeu-compiler/prometeu-build-pipeline/src/main/java/p/studio/compiler/workspaces/stages/LowerToIRVMPipelineStage.java index 2b05550b..2ca11a26 100644 --- a/prometeu-compiler/prometeu-build-pipeline/src/main/java/p/studio/compiler/workspaces/stages/LowerToIRVMPipelineStage.java +++ b/prometeu-compiler/prometeu-build-pipeline/src/main/java/p/studio/compiler/workspaces/stages/LowerToIRVMPipelineStage.java @@ -32,7 +32,7 @@ public class LowerToIRVMPipelineStage implements PipelineStage { .message("[BUILD]: IRBackend is missing before LowerToIRVM stage")); } try { - ctx.irvm = lowerToIRVMService.lower(ctx.irBackend); + ctx.irvm = lowerToIRVMService.lower(ctx.irBackend, ctx.config.vmProfile()); } catch (IRVMLoweringException e) { return BuildingIssueSink.empty() .report(builder -> builder diff --git a/prometeu-compiler/prometeu-build-pipeline/src/test/java/p/studio/compiler/workspaces/stages/LowerToIRVMPipelineStageTest.java b/prometeu-compiler/prometeu-build-pipeline/src/test/java/p/studio/compiler/workspaces/stages/LowerToIRVMPipelineStageTest.java index e277a46d..01cd2b1a 100644 --- a/prometeu-compiler/prometeu-build-pipeline/src/test/java/p/studio/compiler/workspaces/stages/LowerToIRVMPipelineStageTest.java +++ b/prometeu-compiler/prometeu-build-pipeline/src/test/java/p/studio/compiler/workspaces/stages/LowerToIRVMPipelineStageTest.java @@ -11,6 +11,7 @@ import p.studio.utilities.logs.LogAggregator; import p.studio.utilities.structures.ReadOnlyList; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -62,4 +63,36 @@ class LowerToIRVMPipelineStageTest { assertNotNull(ctx.irvm); assertEquals(1, ctx.irvm.module().functions().size()); } + + @Test + void runMustPropagateConfiguredVmProfileToLowering() { + final var ctx = BuilderPipelineContext.compilerContext(new BuilderPipelineConfig(false, ".", "experimental-v1")); + ctx.irBackend = IRBackend.builder() + .executableFunctions(ReadOnlyList.from(new IRBackendExecutableFunction( + new FileId(0), + "app", + "main", + 1, + 0, + 10, + 0, + 0, + 0, + 1, + ReadOnlyList.from(new IRBackendExecutableFunction.Instruction( + IRBackendExecutableFunction.InstructionKind.RET, + "", + "", + null, + null, + Span.none())), + Span.none()))) + .build(); + + final var issues = new LowerToIRVMPipelineStage().run(ctx, LogAggregator.empty()); + + assertFalse(issues.hasErrors()); + assertNotNull(ctx.irvm); + assertEquals("experimental-v1", ctx.irvm.module().vmProfile()); + } } diff --git a/prometeu-compiler/prometeu-build-pipeline/src/test/java/p/studio/compiler/workspaces/stages/OptimizeIRVMPipelineStageTest.java b/prometeu-compiler/prometeu-build-pipeline/src/test/java/p/studio/compiler/workspaces/stages/OptimizeIRVMPipelineStageTest.java index d0a7cb32..80dad9a9 100644 --- a/prometeu-compiler/prometeu-build-pipeline/src/test/java/p/studio/compiler/workspaces/stages/OptimizeIRVMPipelineStageTest.java +++ b/prometeu-compiler/prometeu-build-pipeline/src/test/java/p/studio/compiler/workspaces/stages/OptimizeIRVMPipelineStageTest.java @@ -74,4 +74,26 @@ class OptimizeIRVMPipelineStageTest { assertTrue(issues.hasErrors()); assertEquals(1, issues.size()); } + + @Test + void runMustAcceptSupportedNonDefaultVmProfile() { + final var ctx = BuilderPipelineContext.compilerContext(new BuilderPipelineConfig(false, ".", "experimental-v1")); + ctx.irvm = new IRVMProgram(new IRVMModule( + "experimental-v1", + ReadOnlyList.from(new IRVMFunction( + "main", + 0, + 0, + 0, + 1, + ReadOnlyList.from( + new IRVMInstruction(IRVMOp.HALT, null)))))); + final var stage = new OptimizeIRVMPipelineStage(); + + final var issues = stage.run(ctx, LogAggregator.empty()); + + assertFalse(issues.hasErrors()); + assertNotNull(ctx.optimizedIrvm); + assertEquals("experimental-v1", ctx.optimizedIrvm.module().vmProfile()); + } }