From d11f5583d0f3b941dfe7b27e9e80d051a0a7231e Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Mon, 6 Apr 2026 14:06:15 +0100 Subject: Add full backend support for cranelift --- .../backends/cranelift/CraneliftBackend.java | 136 +++++++++++++++++++-- 1 file changed, 129 insertions(+), 7 deletions(-) (limited to 'src/main/java') diff --git a/src/main/java/org/shedlang/compiler/backends/cranelift/CraneliftBackend.java b/src/main/java/org/shedlang/compiler/backends/cranelift/CraneliftBackend.java index 7a16cc44..584fd7d0 100644 --- a/src/main/java/org/shedlang/compiler/backends/cranelift/CraneliftBackend.java +++ b/src/main/java/org/shedlang/compiler/backends/cranelift/CraneliftBackend.java @@ -1,23 +1,35 @@ package org.shedlang.compiler.backends.cranelift; import com.google.flatbuffers.FlatBufferBuilder; +import org.pcollections.PVector; +import org.shedlang.compiler.backends.Backend; +import org.shedlang.compiler.backends.PatioBackends; import org.shedlang.compiler.backends.llvm.LlvmBackend; import org.shedlang.compiler.backends.llvm.LlvmTarget; import org.shedlang.compiler.backends.paths.PartialTargetPath; +import org.shedlang.compiler.backends.paths.TargetDir; +import org.shedlang.compiler.config.ProfileConfig; +import org.shedlang.compiler.config.ProjectConfig; import org.shedlang.compiler.filesystem.ShedCompilerFiles; import org.shedlang.compiler.patio.PatioCompilationUnit; import org.shedlang.compiler.patio.serialization.PatioToFlatbuffers; import org.shedlang.compiler.runtime.ShedRuntime; +import org.shedlang.compiler.shid.ShidNamespace; +import org.shedlang.compiler.typechecker.TypeInfos; +import org.shedlang.compiler.types.NamespaceName; +import org.shedlang.compiler.util.P; import org.shedlang.compiler.util.processes.ProcessError; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.util.ArrayList; import java.util.List; +import java.util.Optional; import static org.shedlang.compiler.util.processes.ProcessRunner.runInheritIo; -public class CraneliftBackend { +public class CraneliftBackend implements Backend { public static final CraneliftBackend AMD64 = forTarget(LlvmTarget.AMD64); public static CraneliftBackend forTarget(LlvmTarget target) { @@ -33,6 +45,22 @@ public class CraneliftBackend { public Path compileCompilationUnit( PatioCompilationUnit patio, PartialTargetPath partialTargetPath + ) throws IOException, InterruptedException { + return compileCompilationUnit(patio, Optional.empty(), partialTargetPath); + } + + private Path compileMain( + PatioCompilationUnit patio, + String mainFunctionName, + PartialTargetPath partialTargetPath + ) throws IOException, InterruptedException { + return compileCompilationUnit(patio, Optional.of(mainFunctionName), partialTargetPath); + } + + private Path compileCompilationUnit( + PatioCompilationUnit patio, + Optional mainFunctionName, + PartialTargetPath partialTargetPath ) throws IOException, InterruptedException { var fbsBuilder = new FlatBufferBuilder(); var compilationUnitOffset = PatioToFlatbuffers.serializeCompilationUnit(fbsBuilder, patio); @@ -40,14 +68,25 @@ public class CraneliftBackend { // TODO: avoid the copy var patioPath = partialTargetPath.withExtension(".patio"); + Files.createDirectories(patioPath.getParent()); Files.write(patioPath, fbsBuilder.sizedByteArray()); - runInheritIo(List.of( - ShedCompilerFiles.getRoot().resolve("patio-to-cranelift/target/debug/patio-to-cranelift").toString(), - patioPath.toString(), - "--target", - this.target.targetTriple() - )); + var patioToCraneliftArgs = new ArrayList(); + patioToCraneliftArgs.add( + ShedCompilerFiles.getRoot() + .resolve("patio-to-cranelift/target/debug/patio-to-cranelift") + .toString() + ); + patioToCraneliftArgs.add(patioPath.toString()); + patioToCraneliftArgs.add("--target"); + patioToCraneliftArgs.add(this.target.targetTriple()); + + if (mainFunctionName.isPresent()) { + patioToCraneliftArgs.add("--main"); + patioToCraneliftArgs.add(mainFunctionName.get()); + } + + runInheritIo(patioToCraneliftArgs); var objectFilePath = partialTargetPath.withExtension(".o"); return objectFilePath; @@ -61,4 +100,87 @@ public class CraneliftBackend { // TODO: extract linking if it's not specific to LLVM. LlvmBackend.forTarget(this.target).link(inputs, outputPath, shedRuntime); } + + @Override + public String targetName() { + return "cranelift-" + target.targetName(); + } + + @Override + public void compile( + ProjectConfig config, + ProfileConfig profileConfig, + List namespaces, + TypeInfos typeInfos, + TargetDir targetDir + ) throws IOException, InterruptedException { + PatioBackends.compile( + config, + profileConfig, + namespaces, + typeInfos, + new PatioToBinary( + targetDir, + P.vector() + ) + ); + } + + private class PatioToBinary implements PatioBackends.PatioToTarget { + private final TargetDir targetDir; + private final PVector objectFilePaths; + + public PatioToBinary( + TargetDir targetDir, + PVector objectFilePaths + ) { + this.targetDir = targetDir; + this.objectFilePaths = objectFilePaths; + } + + @Override + public PatioBackends.PatioToTarget namespace( + NamespaceName namespaceName, + PatioCompilationUnit patioCompilationUnit + ) throws IOException, InterruptedException { + var objectPath = compileCompilationUnit( + patioCompilationUnit, + this.targetDir.namespace(namespaceName) + ); + + return new PatioToBinary( + this.targetDir, + this.objectFilePaths.plus(objectPath) + ); + } + + @Override + public void bin( + String binName, + PatioCompilationUnit patioCompilationUnit, + String mainFunctionName, + ProfileConfig profileConfig + ) throws IOException, InterruptedException { + var linkInputs = new ArrayList<>(objectFilePaths); + + var mainObjectPath = compileMain( + patioCompilationUnit, + mainFunctionName, + this.targetDir.bin(binName) + ); + linkInputs.add(mainObjectPath); + + var shedRuntime = ShedRuntime.runtime( + target.targetName(), + profileConfig.gc(), + targetDir + ); + + link( + linkInputs, + targetDir.topLevel(binName), + shedRuntime + ); + } + } } -- cgit v1.2.3