15 #include "../PassDetail.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 using namespace circt;
34 class CalyxNativePass :
public CalyxNativeBase<CalyxNativePass> {
36 void runOnOperation()
override;
39 LogicalResult runOnModule(ModuleOp root);
43 void CalyxNativePass::runOnOperation() {
44 ModuleOp mod = getOperation();
45 if (failed(runOnModule(mod)))
46 return signalPassFailure();
49 LogicalResult CalyxNativePass::runOnModule(ModuleOp root) {
50 SmallString<32> execName = llvm::sys::path::filename(
"calyx");
51 llvm::ErrorOr<std::string> exeMb = llvm::sys::findProgramByName(execName);
55 root.emitError() <<
"cannot find the `calyx` executable in PATH. "
56 <<
"Consider installing `calyx` using `cargo install "
57 "calyx` or reading the instructions here: "
58 "https://docs.calyxir.org/#compiler-installation";
61 StringRef calyxExe = exeMb.get();
64 SmallString<32> nativeInputFileName;
65 std::error_code errCode = llvm::sys::fs::getPotentiallyUniqueTempFileName(
66 "calyxNativeTemp",
"", nativeInputFileName);
68 if (std::error_code ok; errCode != ok) {
70 "cannot generate a unique temporary file for input to Calyx compiler");
76 std::unique_ptr<llvm::ToolOutputFile> inputFile =
77 mlir::openOutputFile(nativeInputFileName, &errMsg);
78 if (inputFile ==
nullptr) {
79 root.emitError(errMsg);
86 inputFile->os().flush();
89 SmallString<32> nativeOutputFileName;
90 errCode = llvm::sys::fs::getPotentiallyUniqueTempFileName(
91 "calyxNativeOutTemp",
"", nativeOutputFileName);
92 if (std::error_code ok; errCode != ok) {
94 "cannot generate a unique temporary file name to store output");
98 llvm::SmallVector<StringRef> calyxArgs = {
99 calyxExe, nativeInputFileName,
"-o", nativeOutputFileName,
"-b",
"mlir"};
103 if (!passPipeline.empty()) {
104 llvm::SmallVector<StringRef> passArgs;
105 llvm::StringRef ppRef = passPipeline;
106 ppRef.split(passArgs,
",");
107 for (
auto pass : passArgs) {
110 calyxArgs.push_back(
"-p");
111 calyxArgs.push_back(pass);
115 calyxArgs.push_back(
"-p");
116 calyxArgs.push_back(
"all");
121 calyxArgs.push_back(
"-p");
122 calyxArgs.push_back(
"lower-guards");
124 std::optional<StringRef> redirects[] = {std::nullopt,
125 nativeOutputFileName,
128 int result = llvm::sys::ExecuteAndWait(
129 calyxExe, calyxArgs, std::nullopt,
134 root.emitError() << errMsg;
140 auto bufferRead = llvm::MemoryBuffer::getFile(nativeInputFileName);
141 if (!bufferRead || !*bufferRead) {
142 root.emitError(
"execution of '" + calyxExe +
143 "' did not produce any output file named '" +
144 nativeInputFileName +
"'");
150 parseSourceFile<ModuleOp>(nativeOutputFileName.str(), root.getContext());
151 auto *loadedBlock = loadedMod->getBody();
157 auto *oldBlock = root.getBody();
158 loadedBlock->moveBefore(oldBlock);
164 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()