15 #include "mlir/Pass/Pass.h"
19 #include "mlir/Parser/Parser.h"
20 #include "mlir/Support/FileUtilities.h"
21 #include "llvm/Support/MemoryBuffer.h"
22 #include "llvm/Support/Path.h"
23 #include "llvm/Support/Process.h"
24 #include "llvm/Support/ToolOutputFile.h"
27 #define GEN_PASS_DEF_CALYXNATIVE
28 #include "circt/Conversion/Passes.h.inc"
32 using namespace circt;
39 class CalyxNativePass :
public circt::impl::CalyxNativeBase<CalyxNativePass> {
41 void runOnOperation()
override;
44 LogicalResult runOnModule(ModuleOp root);
48 void CalyxNativePass::runOnOperation() {
49 ModuleOp mod = getOperation();
50 if (failed(runOnModule(mod)))
51 return signalPassFailure();
54 LogicalResult CalyxNativePass::runOnModule(ModuleOp root) {
55 SmallString<32> execName = llvm::sys::path::filename(
"calyx");
56 llvm::ErrorOr<std::string> exeMb = llvm::sys::findProgramByName(execName);
60 root.emitError() <<
"cannot find the `calyx` executable in PATH. "
61 <<
"Consider installing `calyx` using `cargo install "
62 "calyx` or reading the instructions here: "
63 "https://docs.calyxir.org/#compiler-installation";
66 StringRef calyxExe = exeMb.get();
69 SmallString<32> nativeInputFileName;
70 std::error_code errCode = llvm::sys::fs::getPotentiallyUniqueTempFileName(
71 "calyxNativeTemp",
"", nativeInputFileName);
73 if (std::error_code ok; errCode != ok) {
75 "cannot generate a unique temporary file for input to Calyx compiler");
81 std::unique_ptr<llvm::ToolOutputFile> inputFile =
82 mlir::openOutputFile(nativeInputFileName, &errMsg);
83 if (inputFile ==
nullptr) {
84 root.emitError(errMsg);
91 inputFile->os().flush();
94 SmallString<32> nativeOutputFileName;
95 errCode = llvm::sys::fs::getPotentiallyUniqueTempFileName(
96 "calyxNativeOutTemp",
"", nativeOutputFileName);
97 if (std::error_code ok; errCode != ok) {
99 "cannot generate a unique temporary file name to store output");
103 llvm::SmallVector<StringRef> calyxArgs = {
104 calyxExe, nativeInputFileName,
"-o", nativeOutputFileName,
"-b",
"mlir"};
108 if (!passPipeline.empty()) {
109 llvm::SmallVector<StringRef> passArgs;
110 llvm::StringRef ppRef = passPipeline;
111 ppRef.split(passArgs,
",");
112 for (
auto pass : passArgs) {
115 calyxArgs.push_back(
"-p");
116 calyxArgs.push_back(pass);
120 calyxArgs.push_back(
"-p");
121 calyxArgs.push_back(
"all");
126 calyxArgs.push_back(
"-p");
127 calyxArgs.push_back(
"lower-guards");
129 std::optional<StringRef> redirects[] = {std::nullopt,
130 nativeOutputFileName,
133 int result = llvm::sys::ExecuteAndWait(
134 calyxExe, calyxArgs, std::nullopt,
139 root.emitError() << errMsg;
145 auto bufferRead = llvm::MemoryBuffer::getFile(nativeInputFileName);
146 if (!bufferRead || !*bufferRead) {
147 root.emitError(
"execution of '" + calyxExe +
148 "' did not produce any output file named '" +
149 nativeInputFileName +
"'");
155 parseSourceFile<ModuleOp>(nativeOutputFileName.str(), root.getContext());
156 auto *loadedBlock = loadedMod->getBody();
162 auto *oldBlock = root.getBody();
163 loadedBlock->moveBefore(oldBlock);
169 return std::make_unique<CalyxNativePass>();
mlir::LogicalResult exportCalyx(mlir::ModuleOp module, llvm::raw_ostream &os)
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
std::unique_ptr< mlir::Pass > createCalyxNativePass()