re-shape of compiler pipeline
This commit is contained in:
parent
9d2a9955c0
commit
d22c7d16ef
@ -1,15 +1,15 @@
|
||||
package p.studio.compiler.models;
|
||||
|
||||
import p.studio.compiler.messages.BuildingIssue;
|
||||
import p.studio.compiler.source.tables.FileTable;
|
||||
import p.studio.compiler.source.tables.FileTableReader;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public record AnalysisSnapshot(
|
||||
List<BuildingIssue> diagnostics,
|
||||
ResolvedWorkspace resolvedWorkspace,
|
||||
FileTable fileTable,
|
||||
IRBackend irBackend) {
|
||||
FileTableReader fileTable,
|
||||
IRBackendReader irBackend) {
|
||||
public AnalysisSnapshot {
|
||||
diagnostics = List.copyOf(diagnostics);
|
||||
}
|
||||
|
||||
@ -3,9 +3,9 @@ package p.studio.compiler.workspaces;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import p.studio.compiler.exceptions.BuildException;
|
||||
import p.studio.compiler.messages.BuildingIssue;
|
||||
import p.studio.compiler.models.BuilderPipelineContext;
|
||||
import p.studio.compiler.models.AnalysisSnapshot;
|
||||
import p.studio.compiler.models.BuildResult;
|
||||
import p.studio.compiler.models.BuilderPipelineContext;
|
||||
import p.studio.compiler.models.CompileResult;
|
||||
import p.studio.compiler.workspaces.stages.*;
|
||||
import p.studio.utilities.logs.LogAggregator;
|
||||
@ -19,30 +19,45 @@ public class BuilderPipelineService {
|
||||
public final static BuilderPipelineService INSTANCE;
|
||||
|
||||
static {
|
||||
final var stages = List.<PipelineStage>of(
|
||||
|
||||
final var analyses = List.<PipelineStage>of(
|
||||
new ResolveDepsPipelineStage(),
|
||||
new LoadSourcesPipelineStage(),
|
||||
new FrontendPhasePipelineStage(),
|
||||
new FrontendPhasePipelineStage()
|
||||
);
|
||||
|
||||
final var compile = List.<PipelineStage>of(
|
||||
new LowerToIRVMPipelineStage(),
|
||||
new OptimizeIRVMPipelineStage(),
|
||||
new EmitBytecodePipelineStage(),
|
||||
new LinkBytecodePipelineStage(),
|
||||
new VerifyBytecodePipelineStage(),
|
||||
new VerifyBytecodePipelineStage()
|
||||
);
|
||||
|
||||
final var build = List.<PipelineStage>of(
|
||||
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) {
|
||||
this.stages = stages;
|
||||
BuilderPipelineService(
|
||||
final List<PipelineStage> analyses,
|
||||
final List<PipelineStage> compile,
|
||||
final List<PipelineStage> build) {
|
||||
this.analyses = analyses;
|
||||
this.compile = compile;
|
||||
this.build = build;
|
||||
}
|
||||
|
||||
public AnalysisSnapshot analyze(
|
||||
final BuilderPipelineContext ctx,
|
||||
final LogAggregator logs) {
|
||||
final var diagnostics = runToTerminal(ctx, logs, FrontendPhasePipelineStage.class);
|
||||
final var diagnostics = run(ctx, logs, analyses, new ArrayList<>());
|
||||
return new AnalysisSnapshot(
|
||||
diagnostics,
|
||||
ctx.resolvedWorkspace,
|
||||
@ -53,12 +68,8 @@ public class BuilderPipelineService {
|
||||
public CompileResult compile(
|
||||
final BuilderPipelineContext ctx,
|
||||
final LogAggregator logs) {
|
||||
final var diagnostics = runToTerminal(ctx, logs, VerifyBytecodePipelineStage.class);
|
||||
final var analysisSnapshot = new AnalysisSnapshot(
|
||||
diagnostics,
|
||||
ctx.resolvedWorkspace,
|
||||
ctx.fileTable,
|
||||
ctx.irBackend);
|
||||
final var analysisSnapshot = this.analyze(ctx, logs);
|
||||
final var diagnostics = run(ctx, logs, compile, new ArrayList<>(analysisSnapshot.diagnostics()));
|
||||
return new CompileResult(
|
||||
analysisSnapshot,
|
||||
diagnostics,
|
||||
@ -71,31 +82,19 @@ public class BuilderPipelineService {
|
||||
public BuildResult build(
|
||||
final BuilderPipelineContext ctx,
|
||||
final LogAggregator logs) {
|
||||
final var diagnostics = runToTerminal(ctx, logs, WriteBytecodeArtifactPipelineStage.class);
|
||||
final var analysisSnapshot = new AnalysisSnapshot(
|
||||
diagnostics,
|
||||
ctx.resolvedWorkspace,
|
||||
ctx.fileTable,
|
||||
ctx.irBackend);
|
||||
final var compileResult = new CompileResult(
|
||||
analysisSnapshot,
|
||||
diagnostics,
|
||||
ctx.irvm,
|
||||
ctx.optimizedIrvm,
|
||||
ctx.bytecodeModule,
|
||||
ctx.bytecodeBytes);
|
||||
final var compileResult = this.compile(ctx, logs);
|
||||
final var diagnostics = run(ctx, logs, build, new ArrayList<>(compileResult.diagnostics()));
|
||||
return new BuildResult(
|
||||
compileResult,
|
||||
diagnostics,
|
||||
ctx.bytecodeArtifactPath);
|
||||
}
|
||||
|
||||
private List<BuildingIssue> runToTerminal(
|
||||
private List<BuildingIssue> run(
|
||||
final BuilderPipelineContext ctx,
|
||||
final LogAggregator logs,
|
||||
final Class<? extends PipelineStage> terminalStage) {
|
||||
final var diagnostics = new ArrayList<BuildingIssue>();
|
||||
var completed = false;
|
||||
final List<PipelineStage> stages,
|
||||
final List<BuildingIssue> diagnostics) {
|
||||
for (final var builderPipelineStage : stages) {
|
||||
final var issues = builderPipelineStage.run(ctx, logs);
|
||||
diagnostics.addAll(issues.asCollection());
|
||||
@ -103,15 +102,8 @@ public class BuilderPipelineService {
|
||||
if (issues.hasErrors()) {
|
||||
throw new BuildException("issues found on pipeline stage: " + builderPipelineStage.getClass().getSimpleName());
|
||||
}
|
||||
if (terminalStage.isInstance(builderPipelineStage)) {
|
||||
completed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
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());
|
||||
logs.using(log).info("builder pipeline completed successfully");
|
||||
return List.copyOf(diagnostics);
|
||||
}
|
||||
|
||||
|
||||
@ -14,31 +14,36 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
class BuilderPipelineServiceOrderTest {
|
||||
|
||||
@Test
|
||||
void canonicalOrderMustContainOptimizeBetweenLowerAndEmit() throws Exception {
|
||||
final Field field = BuilderPipelineService.class.getDeclaredField("stages");
|
||||
field.setAccessible(true);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
final var stages = (List<PipelineStage>) field.get(BuilderPipelineService.INSTANCE);
|
||||
final var stageTypes = stages.stream().map(Object::getClass).toList();
|
||||
void canonicalOrderMustExposeExpectedStageGroups() throws Exception {
|
||||
final var analyzeStages = stages("analyses");
|
||||
final var compileStages = stages("compile");
|
||||
final var buildStages = stages("build");
|
||||
|
||||
assertEquals(
|
||||
List.of(
|
||||
ResolveDepsPipelineStage.class,
|
||||
LoadSourcesPipelineStage.class,
|
||||
FrontendPhasePipelineStage.class,
|
||||
FrontendPhasePipelineStage.class),
|
||||
analyzeStages);
|
||||
|
||||
assertEquals(
|
||||
List.of(
|
||||
LowerToIRVMPipelineStage.class,
|
||||
OptimizeIRVMPipelineStage.class,
|
||||
EmitBytecodePipelineStage.class,
|
||||
LinkBytecodePipelineStage.class,
|
||||
VerifyBytecodePipelineStage.class,
|
||||
WriteBytecodeArtifactPipelineStage.class),
|
||||
stageTypes);
|
||||
VerifyBytecodePipelineStage.class),
|
||||
compileStages);
|
||||
|
||||
assertEquals(
|
||||
List.of(WriteBytecodeArtifactPipelineStage.class),
|
||||
buildStages);
|
||||
}
|
||||
|
||||
@Test
|
||||
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)
|
||||
.toList();
|
||||
|
||||
@ -47,4 +52,12 @@ class BuilderPipelineServiceOrderTest {
|
||||
assertTrue(methodNames.contains("build"));
|
||||
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
|
||||
@Getter
|
||||
public class IRBackend {
|
||||
public class IRBackend implements IRBackendReader {
|
||||
@Builder.Default
|
||||
private final String entryPointCallableName = "main";
|
||||
@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 p.studio.Container;
|
||||
import p.studio.compiler.messages.BuilderPipelineConfig;
|
||||
import p.studio.compiler.models.BuilderPipelineContext;
|
||||
import p.studio.compiler.workspaces.BuilderPipelineService;
|
||||
import p.studio.projects.ProjectReference;
|
||||
import p.studio.utilities.i18n.I18n;
|
||||
@ -67,7 +68,8 @@ public class ShipperWorkspace extends Workspace {
|
||||
logs.clear();
|
||||
final var logAggregator = LogAggregator.with(logs::appendText);
|
||||
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));
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user