From 7e319ece13eea91de3c15a9a380d3f8c98f3c0f4 Mon Sep 17 00:00:00 2001 From: Sameer Rahmani Date: Fri, 11 Jun 2021 22:06:44 +0100 Subject: [PATCH] Add the bare min pass to convert slir to std dialect --- bin/serene.cpp | 5 +- docs/examples/hello_world.srn | 2 +- include/serene/context.h | 11 ++-- include/serene/passes/slir_lowering.h | 53 +++++++++++++++ include/serene/slir/generator.h | 2 +- src/serene/CMakeLists.txt | 5 +- src/serene/passes/slir_lowering.cpp | 93 +++++++++++++++++++++++++++ src/serene/slir/generator.cpp | 22 +++++-- src/serene/slir/slir.cpp | 7 ++ 9 files changed, 185 insertions(+), 15 deletions(-) create mode 100644 include/serene/passes/slir_lowering.h create mode 100644 src/serene/passes/slir_lowering.cpp diff --git a/bin/serene.cpp b/bin/serene.cpp index 48f5b3b..3a5d940 100644 --- a/bin/serene.cpp +++ b/bin/serene.cpp @@ -1,7 +1,7 @@ -/** +/* -*- C++ -*- * Serene programming language. * - * Copyright (c) 2020 Sameer Rahmani + * Copyright (c) 2019-2021 Sameer Rahmani * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -103,6 +103,7 @@ int main(int argc, char *argv[]) { auto &ast = maybeAst.getValue(); auto ctx = makeSereneContext(); + applyPassManagerCLOptions(ctx->pm); auto ns = makeNamespace(*ctx, "user", llvm::None); auto afterAst = reader::analyze(*ctx, ast); diff --git a/docs/examples/hello_world.srn b/docs/examples/hello_world.srn index 2bd4016..83f89b6 100644 --- a/docs/examples/hello_world.srn +++ b/docs/examples/hello_world.srn @@ -1 +1 @@ -(def a true) +4 80 diff --git a/include/serene/context.h b/include/serene/context.h index a833247..6270584 100644 --- a/include/serene/context.h +++ b/include/serene/context.h @@ -25,12 +25,14 @@ #ifndef SERENE_CONTEXT_H #define SERENE_CONTEXT_H -#include "mlir/IR/MLIRContext.h" #include "serene/environment.h" #include "serene/namespace.h" +#include "serene/passes/slir_lowering.h" #include "serene/slir/dialect.h" -#include "llvm/ADT/StringRef.h" +#include #include +#include +#include namespace serene { @@ -48,7 +50,7 @@ class SereneContext { public: mlir::MLIRContext mlirContext; - + mlir::PassManager pm; /// Insert the given `ns` into the context. The Context object is /// the owner of all the namespaces. The `ns` will overwrite any /// namespace with the same name. @@ -63,8 +65,9 @@ public: std::shared_ptr getNS(llvm::StringRef ns_name); - SereneContext() { + SereneContext() : pm(&mlirContext) { mlirContext.getOrLoadDialect(); + pm.addPass(serene::passes::createSLIRLowerToAffinePass()); }; }; diff --git a/include/serene/passes/slir_lowering.h b/include/serene/passes/slir_lowering.h new file mode 100644 index 0000000..2f0e39f --- /dev/null +++ b/include/serene/passes/slir_lowering.h @@ -0,0 +1,53 @@ +/* -*- C++ -*- + * Serene programming language. + * + * Copyright (c) 2019-2021 Sameer Rahmani + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include "mlir/Dialect/StandardOps/IR/Ops.h" +#include "serene/slir/dialect.h" +#include +#include +#include +#include +#include +#include + +namespace serene::passes { +struct ValueOpLowering : public mlir::OpRewritePattern { + using OpRewritePattern::OpRewritePattern; + + mlir::LogicalResult + matchAndRewrite(serene::slir::ValueOp op, + mlir::PatternRewriter &rewriter) const final; +}; + +struct SLIRToAffinePass + : public mlir::PassWrapper> { + void getDependentDialects(mlir::DialectRegistry ®istry) const override; + void runOnOperation() final; + void runOnModule(); + mlir::ModuleOp getModule(); +}; + +std::unique_ptr createSLIRLowerToAffinePass(); + +} // namespace serene::passes diff --git a/include/serene/slir/generator.h b/include/serene/slir/generator.h index 02e7634..cd9ddf5 100644 --- a/include/serene/slir/generator.h +++ b/include/serene/slir/generator.h @@ -57,7 +57,7 @@ public: this->ns = ctx.getNS(ns_name); }; - mlir::Operation *generate(exprs::Number &); + void generate(exprs::Number &); mlir::Operation *generate(exprs::Expression *); mlir::Value generate(exprs::List *); mlir::ModuleOp generate(); diff --git a/src/serene/CMakeLists.txt b/src/serene/CMakeLists.txt index cda2f60..2a53d71 100644 --- a/src/serene/CMakeLists.txt +++ b/src/serene/CMakeLists.txt @@ -31,7 +31,9 @@ set(HEADER_LIST "${INCLUDE_DIR}/serene/slir/slir.h" "${INCLUDE_DIR}/serene/slir/dialect.h" "${INCLUDE_DIR}/serene/slir/generator.h" - "${INCLUDE_DIR}/serene/namespace.h") + "${INCLUDE_DIR}/serene/namespace.h" + + "${INCLUDE_DIR}/serene/passes/slir_lowering.h") # Make an automatic library - will be static or dynamic based on user setting add_library(serene @@ -62,6 +64,7 @@ add_library(serene slir/dialect.cpp slir/value_op.cpp slir/generator.cpp + passes/slir_lowering.cpp ${HEADER_LIST}) diff --git a/src/serene/passes/slir_lowering.cpp b/src/serene/passes/slir_lowering.cpp new file mode 100644 index 0000000..be02fe0 --- /dev/null +++ b/src/serene/passes/slir_lowering.cpp @@ -0,0 +1,93 @@ +/* -*- C++ -*- + * Serene programming language. + * + * Copyright (c) 2019-2021 Sameer Rahmani + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "serene/passes/slir_lowering.h" +#include + +namespace serene::passes { + +mlir::LogicalResult +ValueOpLowering::matchAndRewrite(serene::slir::ValueOp op, + mlir::PatternRewriter &rewriter) const { + auto value = op.value(); + mlir::Location loc = op.getLoc(); + + // auto std_const = + rewriter.create(loc, (int64_t)value, + rewriter.getI64Type()); + // rewriter.replaceOpWithNewOp(Operation *op, Args &&args...) + // Replace this operation with the generated alloc. + // rewriter.replaceOp(op, alloc); + rewriter.eraseOp(op); + return mlir::success(); +} + +void SLIRToAffinePass::getDependentDialects( + mlir::DialectRegistry ®istry) const { + registry.insert(); +}; + +/// Return the current function being transformed. +mlir::ModuleOp SLIRToAffinePass::getModule() { return this->getOperation(); } + +void SLIRToAffinePass::runOnOperation() { runOnModule(); } + +void SLIRToAffinePass::runOnModule() { + + auto module = getModule(); + + // The first thing to define is the conversion target. This will define the + // final target for this lowering. + mlir::ConversionTarget target(getContext()); + + // We define the specific operations, or dialects, that are legal targets for + // this lowering. In our case, we are lowering to a combination of the + // `Affine`, `MemRef` and `Standard` dialects. + target.addLegalDialect(); + + // We also define the Toy dialect as Illegal so that the conversion will fail + // if any of these operations are *not* converted. Given that we actually want + // a partial lowering, we explicitly mark the Toy operations that don't want + // to lower, `toy.print`, as `legal`. + target.addIllegalDialect(); + // target.addLegalOp(); + + // Now that the conversion target has been defined, we just need to provide + // the set of patterns that will lower the Toy operations. + mlir::RewritePatternSet patterns(&getContext()); + patterns.add(&getContext()); + + // With the target and rewrite patterns defined, we can now attempt the + // conversion. The conversion will signal failure if any of our `illegal` + // operations were not converted successfully. + if (failed(applyPartialConversion(module, target, std::move(patterns)))) + signalPassFailure(); +}; + +std::unique_ptr createSLIRLowerToAffinePass() { + return std::make_unique(); +}; +} // namespace serene::passes diff --git a/src/serene/slir/generator.cpp b/src/serene/slir/generator.cpp index 8d9aed4..67a4da0 100644 --- a/src/serene/slir/generator.cpp +++ b/src/serene/slir/generator.cpp @@ -29,6 +29,7 @@ #include "mlir/IR/MLIRContext.h" #include "mlir/IR/Value.h" #include "serene/exprs/expression.h" +#include "serene/exprs/traits.h" #include "serene/slir/dialect.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/ScopedHashTable.h" @@ -40,9 +41,14 @@ namespace serene { namespace slir { mlir::ModuleOp Generator::generate() { - // for (auto x : ns->Tree()) { - // generate(x.get()); - // } + for (auto &x : ns->getTree()) { + auto *num = llvm::dyn_cast(x.get()); + if (num) { + generate(*num); + } else { + llvm::outs() << "else\n"; + } + } return module; }; @@ -108,7 +114,6 @@ mlir::Value Generator::generate(exprs::List *l) { // // for (auto x : *rest) { // // generate(x.get()); // // } - return builder.create(builder.getUnknownLoc(), (uint64_t)100); }; @@ -179,8 +184,13 @@ mlir::Value Generator::generate(exprs::List *l) { // return fn; // } -mlir::Operation *Generator::generate(exprs::Number &x) { - return builder.create(toMLIRLocation(x.location.start), x.toI64()); +void Generator::generate(exprs::Number &x) { + auto op = + builder.create(toMLIRLocation(x.location.start), x.toI64()); + + if (op) { + module.push_back(op); + } }; /** diff --git a/src/serene/slir/slir.cpp b/src/serene/slir/slir.cpp index 8c17eb0..77d0a0c 100644 --- a/src/serene/slir/slir.cpp +++ b/src/serene/slir/slir.cpp @@ -28,6 +28,7 @@ #include "serene/namespace.h" #include "serene/slir/dialect.h" #include "serene/slir/generator.h" +#include "llvm/Support/raw_ostream.h" #include namespace serene { @@ -52,6 +53,12 @@ void dumpSLIR(serene::SereneContext &ctx, llvm::StringRef ns_name) { assert(ns && "No such a namespace to dump!"); auto module = s.generate(ns_name); + + if (mlir::failed(ctx.pm.run(*module))) { + // TODO: throw a proper errer + llvm::outs() << "Pass manager has faild!\n"; + } + module->dump(); };