Skip to content

Commit

Permalink
More IR mini passes (#11501)
Browse files Browse the repository at this point in the history
  • Loading branch information
Akirathan authored Nov 28, 2024
1 parent 6d9699c commit b5f1106
Show file tree
Hide file tree
Showing 53 changed files with 1,869 additions and 1,274 deletions.
19 changes: 18 additions & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -2949,6 +2949,16 @@ lazy val `runtime-integration-tests` =
(`runtime` / javaModuleName).value -> Seq(javaSrcDir, testClassesDir)
)
},
Test / addOpens := {
val compilerModName = (`runtime-compiler` / javaModuleName).value
// In the tests, we access a private field of org.enso.compiler.pass.PassManager via reflection.
Map(
compilerModName + "/org.enso.compiler.pass" -> Seq(
(`runtime` / javaModuleName).value,
"ALL-UNNAMED"
)
)
},
// runtime-integration-tests does not have module descriptor on its own, so we have
// to explicitly add some modules to the resolution.
Test / addModules := Seq(
Expand Down Expand Up @@ -3232,7 +3242,8 @@ lazy val `runtime-compiler` =
"org.yaml" % "snakeyaml" % snakeyamlVersion % Test,
"org.jline" % "jline" % jlineVersion % Test,
"com.typesafe" % "config" % typesafeConfigVersion % Test,
"org.graalvm.polyglot" % "polyglot" % graalMavenPackagesVersion % Test
"org.graalvm.polyglot" % "polyglot" % graalMavenPackagesVersion % Test,
"org.hamcrest" % "hamcrest-all" % hamcrestVersion % Test
),
Compile / moduleDependencies ++= Seq(
"org.slf4j" % "slf4j-api" % slf4jVersion,
Expand All @@ -3243,6 +3254,7 @@ lazy val `runtime-compiler` =
(`pkg` / Compile / exportedModule).value,
(`runtime-parser` / Compile / exportedModule).value,
(`syntax-rust-definition` / Compile / exportedModule).value,
(`scala-libs-wrapper` / Compile / exportedModule).value,
(`persistance` / Compile / exportedModule).value,
(`editions` / Compile / exportedModule).value
),
Expand Down Expand Up @@ -3271,9 +3283,14 @@ lazy val `runtime-compiler` =
javaModuleName.value
),
Test / patchModules := {
// Patch test-classes into the runtime module. This is standard way to deal with the
// split package problem in unit tests. For example, Maven's surefire plugin does this.
val testClassDir = (Test / productDirectories).value.head
// Patching with sources is useful for compilation, patching with compiled classes for runtime.
val javaSrcDir = (Test / javaSource).value
Map(
javaModuleName.value -> Seq(
javaSrcDir,
testClassDir
)
)
Expand Down
1 change: 1 addition & 0 deletions engine/runtime-compiler/src/main/java/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
requires org.enso.runtime.parser;
requires static org.enso.persistance;
requires org.enso.syntax;
requires org.enso.scala.wrapper;

requires org.openide.util.lookup.RELEASE180;
requires org.slf4j;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package org.enso.compiler;

import org.enso.compiler.core.IR;
import org.enso.compiler.core.ir.MetadataStorage.MetadataPair;
import org.enso.compiler.core.ir.ProcessingPass;
import org.enso.compiler.pass.IRPass;
import org.enso.compiler.pass.IRProcessingPass;
import scala.Option;

/**
Expand All @@ -11,7 +12,7 @@
* <p>This encapsulates the friction of interop between Scala and Java types.
*/
public final class MetadataInteropHelpers {
public static <T> T getMetadataOrNull(IR ir, IRPass pass, Class<T> expectedType) {
public static <T> T getMetadataOrNull(IR ir, IRProcessingPass pass, Class<T> expectedType) {
Option<ProcessingPass.Metadata> option = ir.passData().get(pass);
if (option.isDefined()) {
try {
Expand All @@ -30,7 +31,7 @@ public static <T> T getMetadataOrNull(IR ir, IRPass pass, Class<T> expectedType)
}
}

public static <T> T getMetadata(IR ir, IRPass pass, Class<T> expectedType) {
public static <T> T getMetadata(IR ir, IRProcessingPass pass, Class<T> expectedType) {
T metadataOrNull = getMetadataOrNull(ir, pass, expectedType);
if (metadataOrNull == null) {
throw new IllegalStateException("Missing expected " + pass + " metadata for " + ir + ".");
Expand All @@ -39,5 +40,11 @@ public static <T> T getMetadata(IR ir, IRPass pass, Class<T> expectedType) {
return metadataOrNull;
}

public static <T extends ProcessingPass> void updateMetadata(
IR ir, T pass, ProcessingPass.Metadata metadata) {
var metaPair = new MetadataPair<>(pass, metadata);
ir.passData().update(metaPair);
}

private MetadataInteropHelpers() {}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package org.enso.compiler.pass;

import java.util.Objects;
import org.enso.compiler.core.IR;
import org.enso.compiler.core.ir.Expression;
import org.enso.compiler.core.ir.Module;

/** Utility class for chaining mini passes together. */
final class ChainedMiniPass extends MiniIRPass {
Expand All @@ -18,34 +18,46 @@ static MiniIRPass chain(MiniIRPass firstPass, MiniIRPass secondPass) {
if (firstPass == null) {
return secondPass;
}
if (secondPass == null) {
return firstPass;
}
return new ChainedMiniPass(firstPass, secondPass);
}

@Override
public MiniIRPass prepare(IR parent, Expression current) {
var first = firstPass.prepare(parent, current);
var second = secondPass.prepare(parent, current);
if (first == firstPass && second == secondPass) {
var firstPrepared = firstPass == null ? null : firstPass.prepare(parent, current);
var secondPrepared = secondPass == null ? null : secondPass.prepare(parent, current);
if (firstPrepared == firstPass && secondPrepared == secondPass) {
return this;
} else {
return new ChainedMiniPass(first, second);
return chain(firstPrepared, secondPrepared);
}
}

@Override
public Expression transformExpression(Expression ir) {
var fstIr = firstPass.transformExpression(ir);
var sndIr = secondPass.transformExpression(fstIr);
var fstIr = firstPass == null ? ir : firstPass.transformExpression(ir);
var sndIr = secondPass == null ? fstIr : secondPass.transformExpression(fstIr);
return sndIr;
}

@Override
public Module transformModule(Module moduleIr) {
var firstIr = firstPass == null ? moduleIr : firstPass.transformModule(moduleIr);
var secondIr = secondPass == null ? firstIr : secondPass.transformModule(firstIr);
return secondIr;
}

@Override
public boolean checkPostCondition(IR ir) {
return firstPass.checkPostCondition(ir) && secondPass.checkPostCondition(ir);
var firstCheck = firstPass == null || firstPass.checkPostCondition(ir);
var secondCheck = secondPass == null || secondPass.checkPostCondition(ir);
return firstCheck && secondCheck;
}

@Override
public String toString() {
return Objects.toString(firstPass) + ":" + Objects.toString(secondPass);
return "{" + firstPass + " + " + secondPass + "}";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ public interface IRProcessingPass extends ProcessingPass {
/** The passes that this pass depends _directly_ on to run. */
public Seq<? extends IRProcessingPass> precursorPasses();

/** The passes that are invalidated by running this pass. */
/**
* The passes that are invalidated by running this pass.
*
* <p>If {@code P1} invalidates {@code P2}, and {@code P1} is a precursor of {@code P2}, then
* {@code P1} must finish before {@code P2} starts.
*/
public Seq<? extends IRProcessingPass> invalidatedPasses();
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@ public abstract class MiniIRPass {
*
* @param parent the the parent of the edge
* @param child the child expression element to be be processed.
* @return an instance of the pass to process the child's element subtree
* @return an instance of the pass to process the child's element subtree. If null is returned,
* the subtree of the child element is not processed, including {@code child} (i.e. {@code
* child} is not processed as well).
*/
public MiniIRPass prepare(IR parent, Expression child) {
return this;
Expand Down Expand Up @@ -103,8 +105,9 @@ public String toString() {
* Combines two mini IR passes into one that delegates to both of them.
*
* @param first first mini pass (can be {@code null})
* @param second second mini pass
* @return a combined pass that calls both non-{@code null} of the provided passes
* @param second second mini pass (can be {@code null})
* @return a combined pass that calls both non-{@code null} of the provided passes. {@code null}
* if both provided passes are {@code null}.
*/
public static MiniIRPass combine(MiniIRPass first, MiniIRPass second) {
return ChainedMiniPass.chain(first, second);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ public interface MiniPassFactory extends IRProcessingPass {
* a module.
*
* @param moduleContext A mini pass can optionally save reference to this module context.
* @return May return {@code null} if module compilation is not supported.
* @return May return {@code null} if module compilation is not supported, or if the compilation
* for the given {@code moduleContext} should be skipped.
*/
MiniIRPass createForModuleCompilation(ModuleContext moduleContext);

Expand All @@ -25,7 +26,7 @@ public interface MiniPassFactory extends IRProcessingPass {
* an inline compilation.
*
* @param inlineContext A mini pass can optionally save reference to this inline context.
* @return Must not return {@code null}. Inline compilation should always be supported.
* @return May return {@code null} if the inline compilation is not supported.
*/
MiniIRPass createForInlineCompilation(InlineContext inlineContext);
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ static IR compileDeep(IR root, MiniIRPass miniPass) {
* @param queue queue to put objects in
* @param ir IR to process
* @param miniPass process with this mini pass
* @return {@code true} if the has been modified with new tries to process first
* @return {@code true} if the {@code queue} has been modified with new tries to process first
*/
private static List<IR> enqueueSubExpressions(
Collection<MiniPassTraverser> queue, IR ir, MiniIRPass miniPass) {
Expand All @@ -81,7 +81,9 @@ private static List<IR> enqueueSubExpressions(
(ch) -> {
var preparedMiniPass = miniPass.prepare(ir, ch);
childExpressions.add(ch);
queue.add(new MiniPassTraverser(preparedMiniPass, childExpressions, i[0]++));
if (preparedMiniPass != null) {
queue.add(new MiniPassTraverser(preparedMiniPass, childExpressions, i[0]++));
}
return ch;
});
return childExpressions;
Expand Down
Loading

0 comments on commit b5f1106

Please sign in to comment.