re-shape of compiler pipeline
This commit is contained in:
parent
9d2a9955c0
commit
d22c7d16ef
@ -1,15 +1,15 @@
|
|||||||
package p.studio.compiler.models;
|
package p.studio.compiler.models;
|
||||||
|
|
||||||
import p.studio.compiler.messages.BuildingIssue;
|
import p.studio.compiler.messages.BuildingIssue;
|
||||||
import p.studio.compiler.source.tables.FileTable;
|
import p.studio.compiler.source.tables.FileTableReader;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public record AnalysisSnapshot(
|
public record AnalysisSnapshot(
|
||||||
List<BuildingIssue> diagnostics,
|
List<BuildingIssue> diagnostics,
|
||||||
ResolvedWorkspace resolvedWorkspace,
|
ResolvedWorkspace resolvedWorkspace,
|
||||||
FileTable fileTable,
|
FileTableReader fileTable,
|
||||||
IRBackend irBackend) {
|
IRBackendReader irBackend) {
|
||||||
public AnalysisSnapshot {
|
public AnalysisSnapshot {
|
||||||
diagnostics = List.copyOf(diagnostics);
|
diagnostics = List.copyOf(diagnostics);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,9 +3,9 @@ package p.studio.compiler.workspaces;
|
|||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import p.studio.compiler.exceptions.BuildException;
|
import p.studio.compiler.exceptions.BuildException;
|
||||||
import p.studio.compiler.messages.BuildingIssue;
|
import p.studio.compiler.messages.BuildingIssue;
|
||||||
import p.studio.compiler.models.BuilderPipelineContext;
|
|
||||||
import p.studio.compiler.models.AnalysisSnapshot;
|
import p.studio.compiler.models.AnalysisSnapshot;
|
||||||
import p.studio.compiler.models.BuildResult;
|
import p.studio.compiler.models.BuildResult;
|
||||||
|
import p.studio.compiler.models.BuilderPipelineContext;
|
||||||
import p.studio.compiler.models.CompileResult;
|
import p.studio.compiler.models.CompileResult;
|
||||||
import p.studio.compiler.workspaces.stages.*;
|
import p.studio.compiler.workspaces.stages.*;
|
||||||
import p.studio.utilities.logs.LogAggregator;
|
import p.studio.utilities.logs.LogAggregator;
|
||||||
@ -19,30 +19,45 @@ public class BuilderPipelineService {
|
|||||||
public final static BuilderPipelineService INSTANCE;
|
public final static BuilderPipelineService INSTANCE;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
final var stages = List.<PipelineStage>of(
|
|
||||||
|
final var analyses = List.<PipelineStage>of(
|
||||||
new ResolveDepsPipelineStage(),
|
new ResolveDepsPipelineStage(),
|
||||||
new LoadSourcesPipelineStage(),
|
new LoadSourcesPipelineStage(),
|
||||||
new FrontendPhasePipelineStage(),
|
new FrontendPhasePipelineStage()
|
||||||
|
);
|
||||||
|
|
||||||
|
final var compile = List.<PipelineStage>of(
|
||||||
new LowerToIRVMPipelineStage(),
|
new LowerToIRVMPipelineStage(),
|
||||||
new OptimizeIRVMPipelineStage(),
|
new OptimizeIRVMPipelineStage(),
|
||||||
new EmitBytecodePipelineStage(),
|
new EmitBytecodePipelineStage(),
|
||||||
new LinkBytecodePipelineStage(),
|
new LinkBytecodePipelineStage(),
|
||||||
new VerifyBytecodePipelineStage(),
|
new VerifyBytecodePipelineStage()
|
||||||
|
);
|
||||||
|
|
||||||
|
final var build = List.<PipelineStage>of(
|
||||||
new WriteBytecodeArtifactPipelineStage()
|
new WriteBytecodeArtifactPipelineStage()
|
||||||
);
|
);
|
||||||
INSTANCE = new BuilderPipelineService(stages);
|
|
||||||
|
INSTANCE = new BuilderPipelineService(analyses, compile, build);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final List<PipelineStage> stages;
|
private final List<PipelineStage> analyses;
|
||||||
|
private final List<PipelineStage> compile;
|
||||||
|
private final List<PipelineStage> build;
|
||||||
|
|
||||||
BuilderPipelineService(List<PipelineStage> stages) {
|
BuilderPipelineService(
|
||||||
this.stages = stages;
|
final List<PipelineStage> analyses,
|
||||||
|
final List<PipelineStage> compile,
|
||||||
|
final List<PipelineStage> build) {
|
||||||
|
this.analyses = analyses;
|
||||||
|
this.compile = compile;
|
||||||
|
this.build = build;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AnalysisSnapshot analyze(
|
public AnalysisSnapshot analyze(
|
||||||
final BuilderPipelineContext ctx,
|
final BuilderPipelineContext ctx,
|
||||||
final LogAggregator logs) {
|
final LogAggregator logs) {
|
||||||
final var diagnostics = runToTerminal(ctx, logs, FrontendPhasePipelineStage.class);
|
final var diagnostics = run(ctx, logs, analyses, new ArrayList<>());
|
||||||
return new AnalysisSnapshot(
|
return new AnalysisSnapshot(
|
||||||
diagnostics,
|
diagnostics,
|
||||||
ctx.resolvedWorkspace,
|
ctx.resolvedWorkspace,
|
||||||
@ -53,12 +68,8 @@ public class BuilderPipelineService {
|
|||||||
public CompileResult compile(
|
public CompileResult compile(
|
||||||
final BuilderPipelineContext ctx,
|
final BuilderPipelineContext ctx,
|
||||||
final LogAggregator logs) {
|
final LogAggregator logs) {
|
||||||
final var diagnostics = runToTerminal(ctx, logs, VerifyBytecodePipelineStage.class);
|
final var analysisSnapshot = this.analyze(ctx, logs);
|
||||||
final var analysisSnapshot = new AnalysisSnapshot(
|
final var diagnostics = run(ctx, logs, compile, new ArrayList<>(analysisSnapshot.diagnostics()));
|
||||||
diagnostics,
|
|
||||||
ctx.resolvedWorkspace,
|
|
||||||
ctx.fileTable,
|
|
||||||
ctx.irBackend);
|
|
||||||
return new CompileResult(
|
return new CompileResult(
|
||||||
analysisSnapshot,
|
analysisSnapshot,
|
||||||
diagnostics,
|
diagnostics,
|
||||||
@ -71,31 +82,19 @@ public class BuilderPipelineService {
|
|||||||
public BuildResult build(
|
public BuildResult build(
|
||||||
final BuilderPipelineContext ctx,
|
final BuilderPipelineContext ctx,
|
||||||
final LogAggregator logs) {
|
final LogAggregator logs) {
|
||||||
final var diagnostics = runToTerminal(ctx, logs, WriteBytecodeArtifactPipelineStage.class);
|
final var compileResult = this.compile(ctx, logs);
|
||||||
final var analysisSnapshot = new AnalysisSnapshot(
|
final var diagnostics = run(ctx, logs, build, new ArrayList<>(compileResult.diagnostics()));
|
||||||
diagnostics,
|
|
||||||
ctx.resolvedWorkspace,
|
|
||||||
ctx.fileTable,
|
|
||||||
ctx.irBackend);
|
|
||||||
final var compileResult = new CompileResult(
|
|
||||||
analysisSnapshot,
|
|
||||||
diagnostics,
|
|
||||||
ctx.irvm,
|
|
||||||
ctx.optimizedIrvm,
|
|
||||||
ctx.bytecodeModule,
|
|
||||||
ctx.bytecodeBytes);
|
|
||||||
return new BuildResult(
|
return new BuildResult(
|
||||||
compileResult,
|
compileResult,
|
||||||
diagnostics,
|
diagnostics,
|
||||||
ctx.bytecodeArtifactPath);
|
ctx.bytecodeArtifactPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<BuildingIssue> runToTerminal(
|
private List<BuildingIssue> run(
|
||||||
final BuilderPipelineContext ctx,
|
final BuilderPipelineContext ctx,
|
||||||
final LogAggregator logs,
|
final LogAggregator logs,
|
||||||
final Class<? extends PipelineStage> terminalStage) {
|
final List<PipelineStage> stages,
|
||||||
final var diagnostics = new ArrayList<BuildingIssue>();
|
final List<BuildingIssue> diagnostics) {
|
||||||
var completed = false;
|
|
||||||
for (final var builderPipelineStage : stages) {
|
for (final var builderPipelineStage : stages) {
|
||||||
final var issues = builderPipelineStage.run(ctx, logs);
|
final var issues = builderPipelineStage.run(ctx, logs);
|
||||||
diagnostics.addAll(issues.asCollection());
|
diagnostics.addAll(issues.asCollection());
|
||||||
@ -103,15 +102,8 @@ public class BuilderPipelineService {
|
|||||||
if (issues.hasErrors()) {
|
if (issues.hasErrors()) {
|
||||||
throw new BuildException("issues found on pipeline stage: " + builderPipelineStage.getClass().getSimpleName());
|
throw new BuildException("issues found on pipeline stage: " + builderPipelineStage.getClass().getSimpleName());
|
||||||
}
|
}
|
||||||
if (terminalStage.isInstance(builderPipelineStage)) {
|
|
||||||
completed = true;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
logs.using(log).info("builder pipeline completed successfully");
|
||||||
if (!completed) {
|
|
||||||
throw new BuildException("terminal stage not found on builder pipeline: " + terminalStage.getSimpleName());
|
|
||||||
}
|
|
||||||
logs.using(log).info("builder pipeline completed successfully through " + terminalStage.getSimpleName());
|
|
||||||
return List.copyOf(diagnostics);
|
return List.copyOf(diagnostics);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -14,31 +14,36 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
|||||||
class BuilderPipelineServiceOrderTest {
|
class BuilderPipelineServiceOrderTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void canonicalOrderMustContainOptimizeBetweenLowerAndEmit() throws Exception {
|
void canonicalOrderMustExposeExpectedStageGroups() throws Exception {
|
||||||
final Field field = BuilderPipelineService.class.getDeclaredField("stages");
|
final var analyzeStages = stages("analyses");
|
||||||
field.setAccessible(true);
|
final var compileStages = stages("compile");
|
||||||
|
final var buildStages = stages("build");
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final var stages = (List<PipelineStage>) field.get(BuilderPipelineService.INSTANCE);
|
|
||||||
final var stageTypes = stages.stream().map(Object::getClass).toList();
|
|
||||||
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
List.of(
|
List.of(
|
||||||
ResolveDepsPipelineStage.class,
|
ResolveDepsPipelineStage.class,
|
||||||
LoadSourcesPipelineStage.class,
|
LoadSourcesPipelineStage.class,
|
||||||
FrontendPhasePipelineStage.class,
|
FrontendPhasePipelineStage.class),
|
||||||
|
analyzeStages);
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
List.of(
|
||||||
LowerToIRVMPipelineStage.class,
|
LowerToIRVMPipelineStage.class,
|
||||||
OptimizeIRVMPipelineStage.class,
|
OptimizeIRVMPipelineStage.class,
|
||||||
EmitBytecodePipelineStage.class,
|
EmitBytecodePipelineStage.class,
|
||||||
LinkBytecodePipelineStage.class,
|
LinkBytecodePipelineStage.class,
|
||||||
VerifyBytecodePipelineStage.class,
|
VerifyBytecodePipelineStage.class),
|
||||||
WriteBytecodeArtifactPipelineStage.class),
|
compileStages);
|
||||||
stageTypes);
|
|
||||||
|
assertEquals(
|
||||||
|
List.of(WriteBytecodeArtifactPipelineStage.class),
|
||||||
|
buildStages);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void publicSurfaceMustExposeExplicitEntryPointsWithoutRun() {
|
void publicSurfaceMustExposeExplicitEntryPointsWithoutRun() {
|
||||||
final var methodNames = List.of(BuilderPipelineService.class.getDeclaredMethods()).stream()
|
final var methodNames = List.of(BuilderPipelineService.class.getMethods()).stream()
|
||||||
|
.filter(method -> method.getDeclaringClass().equals(BuilderPipelineService.class))
|
||||||
.map(Method::getName)
|
.map(Method::getName)
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
@ -47,4 +52,12 @@ class BuilderPipelineServiceOrderTest {
|
|||||||
assertTrue(methodNames.contains("build"));
|
assertTrue(methodNames.contains("build"));
|
||||||
assertFalse(methodNames.contains("run"));
|
assertFalse(methodNames.contains("run"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private List<Class<?>> stages(final String fieldName) throws Exception {
|
||||||
|
final Field field = BuilderPipelineService.class.getDeclaredField(fieldName);
|
||||||
|
field.setAccessible(true);
|
||||||
|
final var stages = (List<PipelineStage>) field.get(BuilderPipelineService.INSTANCE);
|
||||||
|
return stages.stream().map(Object::getClass).toList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,7 +13,7 @@ import java.util.LinkedHashSet;
|
|||||||
|
|
||||||
@Builder
|
@Builder
|
||||||
@Getter
|
@Getter
|
||||||
public class IRBackend {
|
public class IRBackend implements IRBackendReader {
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
private final String entryPointCallableName = "main";
|
private final String entryPointCallableName = "main";
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
|
|||||||
@ -0,0 +1,20 @@
|
|||||||
|
package p.studio.compiler.models;
|
||||||
|
|
||||||
|
import p.studio.compiler.source.identifiers.ModuleId;
|
||||||
|
import p.studio.compiler.source.tables.CallableSignatureRef;
|
||||||
|
import p.studio.compiler.source.tables.IntrinsicReference;
|
||||||
|
import p.studio.compiler.source.tables.ModuleReference;
|
||||||
|
import p.studio.utilities.structures.ReadOnlyList;
|
||||||
|
|
||||||
|
public interface IRBackendReader {
|
||||||
|
String getEntryPointCallableName();
|
||||||
|
ModuleId getEntryPointModuleId();
|
||||||
|
ReadOnlyList<IRFunction> getFunctions();
|
||||||
|
ReadOnlyList<IRSyntheticFunction> getSyntheticFunctions();
|
||||||
|
ReadOnlyList<IRGlobal> getGlobals();
|
||||||
|
ReadOnlyList<IRBackendExecutableFunction> getExecutableFunctions();
|
||||||
|
ReadOnlyList<ModuleReference> getModulePool();
|
||||||
|
ReadOnlyList<CallableSignatureRef> getCallableSignatures();
|
||||||
|
ReadOnlyList<IntrinsicReference> getIntrinsicPool();
|
||||||
|
IRReservedMetadata getReservedMetadata();
|
||||||
|
}
|
||||||
@ -7,6 +7,7 @@ import javafx.scene.layout.BorderPane;
|
|||||||
import javafx.scene.layout.StackPane;
|
import javafx.scene.layout.StackPane;
|
||||||
import p.studio.Container;
|
import p.studio.Container;
|
||||||
import p.studio.compiler.messages.BuilderPipelineConfig;
|
import p.studio.compiler.messages.BuilderPipelineConfig;
|
||||||
|
import p.studio.compiler.models.BuilderPipelineContext;
|
||||||
import p.studio.compiler.workspaces.BuilderPipelineService;
|
import p.studio.compiler.workspaces.BuilderPipelineService;
|
||||||
import p.studio.projects.ProjectReference;
|
import p.studio.projects.ProjectReference;
|
||||||
import p.studio.utilities.i18n.I18n;
|
import p.studio.utilities.i18n.I18n;
|
||||||
@ -67,7 +68,8 @@ public class ShipperWorkspace extends Workspace {
|
|||||||
logs.clear();
|
logs.clear();
|
||||||
final var logAggregator = LogAggregator.with(logs::appendText);
|
final var logAggregator = LogAggregator.with(logs::appendText);
|
||||||
final var config = new BuilderPipelineConfig(false, projectReference.rootPath().toString());
|
final var config = new BuilderPipelineConfig(false, projectReference.rootPath().toString());
|
||||||
BuilderPipelineService.INSTANCE.run(config, logAggregator);
|
final var ctx = BuilderPipelineContext.fromConfig(config);
|
||||||
|
BuilderPipelineService.INSTANCE.build(ctx, logAggregator);
|
||||||
});
|
});
|
||||||
|
|
||||||
clearButton.textProperty().bind(Container.i18n().bind(I18n.WORKSPACE_SHIPPER_BUTTON_CLEAR));
|
clearButton.textProperty().bind(Container.i18n().bind(I18n.WORKSPACE_SHIPPER_BUTTON_CLEAR));
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user