Add the NsOp to represent namespaces
This commit is contained in:
parent
0d7f51da8a
commit
97b31e8cb0
|
@ -16,6 +16,7 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "serene/passes.h"
|
||||||
#include "serene/slir/dialect.h"
|
#include "serene/slir/dialect.h"
|
||||||
|
|
||||||
#include <mlir/Dialect/Arithmetic/IR/Arithmetic.h>
|
#include <mlir/Dialect/Arithmetic/IR/Arithmetic.h>
|
||||||
|
@ -28,7 +29,9 @@ int main(int argc, char **argv) {
|
||||||
|
|
||||||
serene::slir::registerTo(registry);
|
serene::slir::registerTo(registry);
|
||||||
registry.insert<mlir::arith::ArithmeticDialect, mlir::func::FuncDialect>();
|
registry.insert<mlir::arith::ArithmeticDialect, mlir::func::FuncDialect>();
|
||||||
// TODO: Register passes here
|
|
||||||
|
serene::passes::registerAllPasses();
|
||||||
|
|
||||||
return static_cast<int>(
|
return static_cast<int>(
|
||||||
mlir::failed(mlir::MlirOptMain(argc, argv, "slir-opt", registry)));
|
mlir::failed(mlir::MlirOptMain(argc, argv, "slir-opt", registry)));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
module @some.ns {
|
serene.ns @some.ns {
|
||||||
// Value operator ----
|
// Value operator ----
|
||||||
%0 = "serene.value"(){value= 3} : () -> i64
|
%0 = "serene.value"(){value= 3} : () -> i64
|
||||||
// compact form
|
// compact form
|
||||||
%1 = serene.value 3 : i32
|
%1 = serene.value 3 : i32
|
||||||
|
|
||||||
|
%x = serene.symbol "some.ns" "x"
|
||||||
// Def operator ----
|
// Def operator ----
|
||||||
%foo = "serene.def"(%0){sym_name = "foo"}: (i64) -> !serene.symbol
|
%foo = "serene.define"(%0){sym_name = "foo"}: (i64) -> !serene.symbol
|
||||||
// compact form
|
// compact form
|
||||||
%bar = serene.def "bar", %0 : i64
|
%bar = serene.define "bar", %0 : i64
|
||||||
|
|
||||||
// Fn operator ----
|
// Fn operator ----
|
||||||
%f1 = "serene.fn"()({
|
%f1 = "serene.fn"()({
|
||||||
|
@ -15,7 +16,7 @@ module @some.ns {
|
||||||
%2 = serene.value 3 : i32
|
%2 = serene.value 3 : i32
|
||||||
|
|
||||||
// Def operator ----
|
// 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
|
serene.ret %baz : !serene.symbol
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -23,10 +24,10 @@ module @some.ns {
|
||||||
%3 = serene.value 4 : i32
|
%3 = serene.value 4 : i32
|
||||||
|
|
||||||
// Def operator ----
|
// 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
|
serene.ret %baz1 : !serene.symbol
|
||||||
^b2:
|
^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
|
serene.ret %baz2 : !serene.symbol
|
||||||
}){name = "some-fn", return_type = i32} : () -> !serene.fn
|
}){name = "some-fn", return_type = i32} : () -> !serene.fn
|
||||||
|
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
add_subdirectory("serene/slir/")
|
add_subdirectory("serene/slir/")
|
||||||
|
add_subdirectory("serene/passes/")
|
||||||
add_subdirectory("serene/errors/")
|
add_subdirectory("serene/errors/")
|
||||||
|
|
|
@ -19,10 +19,16 @@
|
||||||
#ifndef SERENE_PASSES_H
|
#ifndef SERENE_PASSES_H
|
||||||
#define SERENE_PASSES_H
|
#define SERENE_PASSES_H
|
||||||
|
|
||||||
|
#include "serene/export.h"
|
||||||
|
|
||||||
#include <mlir/Pass/Pass.h>
|
#include <mlir/Pass/Pass.h>
|
||||||
|
|
||||||
namespace serene::passes {
|
namespace serene::passes {
|
||||||
|
|
||||||
|
/// Return a pass to lower the serene.symbol op
|
||||||
|
SERENE_EXPORT std::unique_ptr<mlir::Pass> createLowerSymbol();
|
||||||
|
|
||||||
|
SERENE_EXPORT void registerAllPasses();
|
||||||
/// Return a pass to convert SLIR dialect to built-in dialects
|
/// Return a pass to convert SLIR dialect to built-in dialects
|
||||||
/// of MLIR.
|
/// of MLIR.
|
||||||
std::unique_ptr<mlir::Pass> createSLIRLowerToMLIRPass();
|
std::unique_ptr<mlir::Pass> createSLIRLowerToMLIRPass();
|
||||||
|
|
|
@ -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)
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* Serene Programming Language
|
||||||
|
*
|
||||||
|
* Copyright (c) 2019-2022 Sameer Rahmani <lxsameer@gnu.org>
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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
|
|
@ -1,4 +1,4 @@
|
||||||
/* -*- C++ -*-
|
/*
|
||||||
* Serene Programming Language
|
* Serene Programming Language
|
||||||
*
|
*
|
||||||
* Copyright (c) 2019-2022 Sameer Rahmani <lxsameer@gnu.org>
|
* Copyright (c) 2019-2022 Sameer Rahmani <lxsameer@gnu.org>
|
||||||
|
@ -21,7 +21,9 @@
|
||||||
|
|
||||||
include "mlir/IR/OpBase.td"
|
include "mlir/IR/OpBase.td"
|
||||||
include "mlir/Interfaces/CallInterfaces.td"
|
include "mlir/Interfaces/CallInterfaces.td"
|
||||||
|
include "mlir/IR/RegionKindInterface.td"
|
||||||
include "mlir/IR/SymbolInterfaces.td"
|
include "mlir/IR/SymbolInterfaces.td"
|
||||||
|
include "mlir/IR/OpAsmInterface.td"
|
||||||
|
|
||||||
// Base class for Serene dialect operations. This operation inherits from the base
|
// Base class for Serene dialect operations. This operation inherits from the base
|
||||||
// `Op` class in OpBase.td, and provides:
|
// `Op` class in OpBase.td, and provides:
|
||||||
|
@ -75,21 +77,48 @@ def ValueOp : Serene_Op<"value", [
|
||||||
let assemblyFormat = "attr-dict $value";
|
let assemblyFormat = "attr-dict $value";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Symbol Op
|
||||||
|
def SymbolOp : Serene_Op<"symbol", [
|
||||||
|
ConstantLike, NoSideEffect, IsolatedFromAbove
|
||||||
|
]> {
|
||||||
|
|
||||||
// Def
|
let summary = "This operation is the compile time contructor for symbol type";
|
||||||
def DefOp: Serene_Op<"def", [Symbol]> {
|
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 summary = "This operation defines a global binding in the current namespace";
|
||||||
let description = [{
|
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.
|
symbol type.
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
```mlir
|
```mlir
|
||||||
%foo = "serene.def"(%0){name = "foo"}: (i64) -> !serene.symbol
|
%foo = "serene.define"(%0){name = "foo"}: (i64) -> !serene.symbol
|
||||||
|
|
||||||
// compact form
|
// 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<StrAttr>:$sym_visibility);
|
||||||
|
|
||||||
|
let regions = (region SizedRegion<1>:$body);
|
||||||
|
|
||||||
|
let assemblyFormat = "$sym_name attr-dict-with-keyword $body";
|
||||||
|
|
||||||
|
let builders = [
|
||||||
|
OpBuilder<(ins CArg<"llvm::Optional<llvm::StringRef>", "{}">:$name)>
|
||||||
|
];
|
||||||
|
|
||||||
|
let extraClassDeclaration = [{
|
||||||
|
/// Construct a namespace from the given location with an optional name.
|
||||||
|
// static NsOp create(slir::reader::LocationRange loc, Optional<StringRef> 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
|
#endif // SERENE_DIALECT_OPS
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* -*- C++ -*-
|
/*
|
||||||
* Serene Programming Language
|
* Serene Programming Language
|
||||||
*
|
*
|
||||||
* Copyright (c) 2019-2022 Sameer Rahmani <lxsameer@gnu.org>
|
* Copyright (c) 2019-2022 Sameer Rahmani <lxsameer@gnu.org>
|
||||||
|
|
|
@ -108,7 +108,7 @@ else()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Generate the tablegen ODS files before this target
|
# 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
|
# We need this directory, and users of our library will need it too
|
||||||
target_include_directories(serene PUBLIC "$<BUILD_INTERFACE:${INCLUDE_DIR}>")
|
target_include_directories(serene PUBLIC "$<BUILD_INTERFACE:${INCLUDE_DIR}>")
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "serene/utils.h"
|
#include "serene/utils.h"
|
||||||
|
|
||||||
#include <llvm/Support/Casting.h>
|
#include <llvm/Support/Casting.h>
|
||||||
|
#include <llvm/Support/raw_ostream.h>
|
||||||
#include <mlir/Dialect/Arithmetic/IR/Arithmetic.h>
|
#include <mlir/Dialect/Arithmetic/IR/Arithmetic.h>
|
||||||
#include <mlir/Dialect/Func/IR/FuncOps.h>
|
#include <mlir/Dialect/Func/IR/FuncOps.h>
|
||||||
#include <mlir/Dialect/LLVMIR/LLVMDialect.h>
|
#include <mlir/Dialect/LLVMIR/LLVMDialect.h>
|
||||||
|
@ -34,6 +35,27 @@
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
namespace serene::passes {
|
namespace serene::passes {
|
||||||
|
#define GEN_PASS_CLASSES
|
||||||
|
#include "serene/passes/passes.h.inc"
|
||||||
|
|
||||||
|
class LowerSymbol : public LowerSymbolBase<LowerSymbol> {
|
||||||
|
void runOnOperation() override { llvm::outs() << "here\n"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
std::unique_ptr<mlir::Pass> createLowerSymbol() {
|
||||||
|
return std::make_unique<LowerSymbol>();
|
||||||
|
}
|
||||||
|
|
||||||
|
class LowerSLIR : public LowerSLIRBase<LowerSLIR> {
|
||||||
|
void runOnOperation() override { llvm::outs() << "here\n"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
std::unique_ptr<mlir::Pass> createLowerSLIR() {
|
||||||
|
return std::make_unique<LowerSLIR>();
|
||||||
|
}
|
||||||
|
|
||||||
|
#define GEN_PASS_REGISTRATION
|
||||||
|
#include "serene/passes/passes.h.inc"
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// ValueOp lowering to constant op
|
// ValueOp lowering to constant op
|
||||||
|
@ -191,4 +213,6 @@ void SLIRToMLIRPass::runOnModule() {
|
||||||
std::unique_ptr<mlir::Pass> createSLIRLowerToMLIRPass() {
|
std::unique_ptr<mlir::Pass> createSLIRLowerToMLIRPass() {
|
||||||
return std::make_unique<SLIRToMLIRPass>();
|
return std::make_unique<SLIRToMLIRPass>();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void registerAllPasses() { registerPasses(); }
|
||||||
} // namespace serene::passes
|
} // namespace serene::passes
|
||||||
|
|
|
@ -24,4 +24,16 @@
|
||||||
#include <mlir/IR/BuiltinAttributes.h>
|
#include <mlir/IR/BuiltinAttributes.h>
|
||||||
#include <mlir/IR/OperationSupport.h>
|
#include <mlir/IR/OperationSupport.h>
|
||||||
|
|
||||||
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<mlir::DataLayoutSpecInterface>())
|
||||||
|
return spec;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace serene::slir
|
||||||
|
|
Loading…
Reference in New Issue