diff --git a/devtools/slir-opt.cpp b/devtools/slir-opt.cpp
index 3638609..36cf7f2 100644
--- a/devtools/slir-opt.cpp
+++ b/devtools/slir-opt.cpp
@@ -16,6 +16,7 @@
* along with this program. If not, see .
*/
+#include "serene/passes.h"
#include "serene/slir/dialect.h"
#include
@@ -28,7 +29,9 @@ int main(int argc, char **argv) {
serene::slir::registerTo(registry);
registry.insert();
- // TODO: Register passes here
+
+ serene::passes::registerAllPasses();
+
return static_cast(
mlir::failed(mlir::MlirOptMain(argc, argv, "slir-opt", registry)));
}
diff --git a/docs/examples/slir/hello_world.mlir b/docs/examples/slir/hello_world.mlir
index e3413e3..ec33768 100644
--- a/docs/examples/slir/hello_world.mlir
+++ b/docs/examples/slir/hello_world.mlir
@@ -1,13 +1,14 @@
-module @some.ns {
+serene.ns @some.ns {
// Value operator ----
%0 = "serene.value"(){value= 3} : () -> i64
// compact form
%1 = serene.value 3 : i32
+ %x = serene.symbol "some.ns" "x"
// Def operator ----
- %foo = "serene.def"(%0){sym_name = "foo"}: (i64) -> !serene.symbol
+ %foo = "serene.define"(%0){sym_name = "foo"}: (i64) -> !serene.symbol
// compact form
- %bar = serene.def "bar", %0 : i64
+ %bar = serene.define "bar", %0 : i64
// Fn operator ----
%f1 = "serene.fn"()({
@@ -15,7 +16,7 @@ module @some.ns {
%2 = serene.value 3 : i32
// Def operator ----
- %baz = "serene.def"(%fnarg1){sym_name = "baz"}: (i1) -> !serene.symbol
+ %baz = "serene.define"(%fnarg1){sym_name = "baz"}: (i1) -> !serene.symbol
serene.ret %baz : !serene.symbol
},
{
@@ -23,10 +24,10 @@ module @some.ns {
%3 = serene.value 4 : i32
// Def operator ----
- %baz1 = "serene.def"(%3){sym_name = "baz"}: (i32) -> !serene.symbol
+ %baz1 = "serene.define"(%3){sym_name = "baz"}: (i32) -> !serene.symbol
serene.ret %baz1 : !serene.symbol
^b2:
- %baz2 = "serene.def"(%3){sym_name = "baz"}: (i32) -> !serene.symbol
+ %baz2 = "serene.define"(%3){sym_name = "baz"}: (i32) -> !serene.symbol
serene.ret %baz2 : !serene.symbol
}){name = "some-fn", return_type = i32} : () -> !serene.fn
diff --git a/libserene/include/CMakeLists.txt b/libserene/include/CMakeLists.txt
index 1542268..1c51b2a 100644
--- a/libserene/include/CMakeLists.txt
+++ b/libserene/include/CMakeLists.txt
@@ -1,2 +1,3 @@
add_subdirectory("serene/slir/")
+add_subdirectory("serene/passes/")
add_subdirectory("serene/errors/")
diff --git a/libserene/include/serene/passes.h b/libserene/include/serene/passes.h
index 5e28890..47db599 100644
--- a/libserene/include/serene/passes.h
+++ b/libserene/include/serene/passes.h
@@ -19,10 +19,16 @@
#ifndef SERENE_PASSES_H
#define SERENE_PASSES_H
+#include "serene/export.h"
+
#include
namespace serene::passes {
+/// Return a pass to lower the serene.symbol op
+SERENE_EXPORT std::unique_ptr createLowerSymbol();
+
+SERENE_EXPORT void registerAllPasses();
/// Return a pass to convert SLIR dialect to built-in dialects
/// of MLIR.
std::unique_ptr createSLIRLowerToMLIRPass();
diff --git a/libserene/include/serene/passes/CMakeLists.txt b/libserene/include/serene/passes/CMakeLists.txt
new file mode 100644
index 0000000..0b30d08
--- /dev/null
+++ b/libserene/include/serene/passes/CMakeLists.txt
@@ -0,0 +1,9 @@
+set(LLVM_TARGET_DEFINITIONS passes.td)
+
+mlir_tablegen(passes.h.inc -gen-pass-decls)
+
+if(SERENE_ENABLE_DOCS)
+ mlir_tablegen(passes.md.inc -gen-pass-doc)
+endif()
+
+add_public_tablegen_target(SerenePassGen)
diff --git a/libserene/include/serene/passes/passes.td b/libserene/include/serene/passes/passes.td
new file mode 100644
index 0000000..be5e8ef
--- /dev/null
+++ b/libserene/include/serene/passes/passes.td
@@ -0,0 +1,49 @@
+/*
+ * Serene Programming Language
+ *
+ * Copyright (c) 2019-2022 Sameer Rahmani
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifndef SERENE_PASSES_TD
+#define SERENE_PASSES_TD
+
+include "mlir/Pass/PassBase.td"
+
+def LowerSymbol : Pass<"lower-symbol", "slir::SymbolOp"> {
+ let summary = "Lowers `serene.symbol` operation to LLVM dialect";
+
+ let description = [{Lowers `serene.symbol` operation to LLVM dialect as an struct}];
+
+ // This is how we can create the default instance of this pass.
+ // via `createLowerSymbol` function
+ let constructor = "serene::passes::createLowerSymbol()";
+}
+
+def LowerSLIR : Pass<"lower-slir", "slir::NsOp"> {
+ let summary = "Lowers the SLIR dialect to LLVM IR indirectly";
+
+ let description = [{
+ Lowers the SLIR dialect to LLVM IR indirectly meaning
+ that it will lower SLIR to other dialects that in turn will
+ eventually lower to llvm ir.
+ }];
+
+ // This is how we can create the default instance of this pass.
+ // via `createLowerSymbol` function
+ let constructor = "serene::passes::createLowerSLIR()";
+ let dependentDialects = ["slir::SereneDialect", "mlir::func::FuncDialect"];
+}
+
+#endif // SERENE_PASSES_TD
diff --git a/libserene/include/serene/slir/ops.td b/libserene/include/serene/slir/ops.td
index 7e6ca3a..ef65d7a 100644
--- a/libserene/include/serene/slir/ops.td
+++ b/libserene/include/serene/slir/ops.td
@@ -1,4 +1,4 @@
-/* -*- C++ -*-
+/*
* Serene Programming Language
*
* Copyright (c) 2019-2022 Sameer Rahmani
@@ -21,7 +21,9 @@
include "mlir/IR/OpBase.td"
include "mlir/Interfaces/CallInterfaces.td"
+include "mlir/IR/RegionKindInterface.td"
include "mlir/IR/SymbolInterfaces.td"
+include "mlir/IR/OpAsmInterface.td"
// Base class for Serene dialect operations. This operation inherits from the base
// `Op` class in OpBase.td, and provides:
@@ -75,21 +77,48 @@ def ValueOp : Serene_Op<"value", [
let assemblyFormat = "attr-dict $value";
}
+// Symbol Op
+def SymbolOp : Serene_Op<"symbol", [
+ ConstantLike, NoSideEffect, IsolatedFromAbove
+]> {
-// Def
-def DefOp: Serene_Op<"def", [Symbol]> {
+ let summary = "This operation is the compile time contructor for symbol type";
+ let description = [{
+ The `symbol` operation produces an SSA value that holds a value of type
+ symbol at compile time.
+
+ Example:
+
+ ```
+
+ %1 = serene.symbol "some.ns" "symbol_name"
+
+ // Equivalent generic form
+ %1 = "serene.symbol"() {ns = "some.ns", name = "symbol_name"} : () -> i32
+ ```
+ }];
+
+ let arguments = (ins StrAttr:$ns, StrAttr:$name);
+ let results = (outs SereneSymbol:$result);
+
+ let assemblyFormat = "attr-dict $ns $name";
+}
+
+
+// Define
+def DefnieOp: Serene_Op<"define", [Symbol]> {
let summary = "This operation defines a global binding in the current namespace";
let description = [{
- `def` defines a global binding in the current namespace. It always return a
+ `define` defines a global binding in the current namespace. It always return a
symbol type.
Examples:
```mlir
- %foo = "serene.def"(%0){name = "foo"}: (i64) -> !serene.symbol
+ %foo = "serene.define"(%0){name = "foo"}: (i64) -> !serene.symbol
// compact form
- %bar = serene.def "bar", %0 : i64
+ %bar = serene.define "bar", %0 : i64
```
}];
@@ -174,4 +203,63 @@ def CallOp : Serene_Op<"call",
}];
}
+def NsOp : Serene_Op<"ns", [
+ AffineScope, IsolatedFromAbove, NoRegionArguments, SymbolTable, Symbol,
+ OpAsmOpInterface
+] # GraphRegionNoTerminator.traits> {
+ let summary = "This operation represents a Serene namespace.";
+ let description = [{
+ The `serene.ns` operation represents a namespace that will eventually
+ lowers to a `mlir::ModuleOp`.
+
+ Example:
+
+ ```mlir
+ serene.ns @some.ns {
+ ....
+ }
+ ```
+ }];
+
+ // TODO: Create a new Attr type that is an array to represent
+ // required namespaces
+ let arguments = (ins SymbolNameAttr:$sym_name,
+ OptionalAttr:$sym_visibility);
+
+ let regions = (region SizedRegion<1>:$body);
+
+ let assemblyFormat = "$sym_name attr-dict-with-keyword $body";
+
+ let builders = [
+ OpBuilder<(ins CArg<"llvm::Optional", "{}">:$name)>
+ ];
+
+ let extraClassDeclaration = [{
+ /// Construct a namespace from the given location with an optional name.
+ // static NsOp create(slir::reader::LocationRange loc, Optional name = llvm::None);
+
+ /// Return the name of this module if present.
+ llvm::StringRef getName() { return sym_name(); }
+
+ //===------------------------------------------------------------------===//
+ // SymbolOpInterface Methods
+ //===------------------------------------------------------------------===//
+
+ /// A ModuleOp may optionally define a symbol.
+ bool isOptionalSymbol() { return false; }
+
+ //===------------------------------------------------------------------===//
+ // DataLayoutOpInterface Methods
+ //===------------------------------------------------------------------===//
+ mlir::DataLayoutSpecInterface getDataLayoutSpec();
+
+ //===------------------------------------------------------------------===//
+ // OpAsmOpInterface Methods
+ //===------------------------------------------------------------------===//
+ static ::llvm::StringRef getDefaultDialect() {
+ return "builtin";
+ }
+ }];
+}
+
#endif // SERENE_DIALECT_OPS
diff --git a/libserene/include/serene/slir/types.td b/libserene/include/serene/slir/types.td
index 26aef12..b0b0c7d 100644
--- a/libserene/include/serene/slir/types.td
+++ b/libserene/include/serene/slir/types.td
@@ -1,4 +1,4 @@
-/* -*- C++ -*-
+/*
* Serene Programming Language
*
* Copyright (c) 2019-2022 Sameer Rahmani
diff --git a/libserene/lib/CMakeLists.txt b/libserene/lib/CMakeLists.txt
index 261c3ba..c69f2ed 100644
--- a/libserene/lib/CMakeLists.txt
+++ b/libserene/lib/CMakeLists.txt
@@ -108,7 +108,7 @@ else()
endif()
# Generate the tablegen ODS files before this target
-add_dependencies(serene SereneTablegen SereneDialectGen SereneErrorGen)
+add_dependencies(serene SereneTablegen SereneDialectGen SerenePassGen SereneErrorGen)
# We need this directory, and users of our library will need it too
target_include_directories(serene PUBLIC "$")
diff --git a/libserene/lib/passes/slir_lowering.cpp b/libserene/lib/passes/slir_lowering.cpp
index afeda8e..32ed239 100644
--- a/libserene/lib/passes/slir_lowering.cpp
+++ b/libserene/lib/passes/slir_lowering.cpp
@@ -21,6 +21,7 @@
#include "serene/utils.h"
#include
+#include
#include
#include
#include
@@ -34,6 +35,27 @@
#include
namespace serene::passes {
+#define GEN_PASS_CLASSES
+#include "serene/passes/passes.h.inc"
+
+class LowerSymbol : public LowerSymbolBase {
+ void runOnOperation() override { llvm::outs() << "here\n"; }
+};
+
+std::unique_ptr createLowerSymbol() {
+ return std::make_unique();
+}
+
+class LowerSLIR : public LowerSLIRBase {
+ void runOnOperation() override { llvm::outs() << "here\n"; }
+};
+
+std::unique_ptr createLowerSLIR() {
+ return std::make_unique();
+}
+
+#define GEN_PASS_REGISTRATION
+#include "serene/passes/passes.h.inc"
// ----------------------------------------------------------------------------
// ValueOp lowering to constant op
@@ -191,4 +213,6 @@ void SLIRToMLIRPass::runOnModule() {
std::unique_ptr createSLIRLowerToMLIRPass() {
return std::make_unique();
};
+
+void registerAllPasses() { registerPasses(); }
} // namespace serene::passes
diff --git a/libserene/lib/slir/ops.cpp b/libserene/lib/slir/ops.cpp
index 38e2fda..159dbf3 100644
--- a/libserene/lib/slir/ops.cpp
+++ b/libserene/lib/slir/ops.cpp
@@ -24,4 +24,16 @@
#include
#include
-namespace serene::slir {} // namespace serene::slir
+namespace serene::slir {
+
+mlir::DataLayoutSpecInterface NsOp::getDataLayoutSpec() {
+ // Take the first and only (if present) attribute that implements the
+ // interface. This needs a linear search, but is called only once per data
+ // layout object construction that is used for repeated queries.
+ for (mlir::NamedAttribute attr : getOperation()->getAttrs())
+ if (auto spec = attr.getValue().dyn_cast())
+ return spec;
+ return {};
+}
+
+} // namespace serene::slir