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/>.
|
||||
*/
|
||||
|
||||
#include "serene/passes.h"
|
||||
#include "serene/slir/dialect.h"
|
||||
|
||||
#include <mlir/Dialect/Arithmetic/IR/Arithmetic.h>
|
||||
|
@ -28,7 +29,9 @@ int main(int argc, char **argv) {
|
|||
|
||||
serene::slir::registerTo(registry);
|
||||
registry.insert<mlir::arith::ArithmeticDialect, mlir::func::FuncDialect>();
|
||||
// TODO: Register passes here
|
||||
|
||||
serene::passes::registerAllPasses();
|
||||
|
||||
return static_cast<int>(
|
||||
mlir::failed(mlir::MlirOptMain(argc, argv, "slir-opt", registry)));
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
add_subdirectory("serene/slir/")
|
||||
add_subdirectory("serene/passes/")
|
||||
add_subdirectory("serene/errors/")
|
||||
|
|
|
@ -19,10 +19,16 @@
|
|||
#ifndef SERENE_PASSES_H
|
||||
#define SERENE_PASSES_H
|
||||
|
||||
#include "serene/export.h"
|
||||
|
||||
#include <mlir/Pass/Pass.h>
|
||||
|
||||
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
|
||||
/// of MLIR.
|
||||
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
|
||||
*
|
||||
* Copyright (c) 2019-2022 Sameer Rahmani <lxsameer@gnu.org>
|
||||
|
@ -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<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
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- C++ -*-
|
||||
/*
|
||||
* Serene Programming Language
|
||||
*
|
||||
* Copyright (c) 2019-2022 Sameer Rahmani <lxsameer@gnu.org>
|
||||
|
|
|
@ -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 "$<BUILD_INTERFACE:${INCLUDE_DIR}>")
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "serene/utils.h"
|
||||
|
||||
#include <llvm/Support/Casting.h>
|
||||
#include <llvm/Support/raw_ostream.h>
|
||||
#include <mlir/Dialect/Arithmetic/IR/Arithmetic.h>
|
||||
#include <mlir/Dialect/Func/IR/FuncOps.h>
|
||||
#include <mlir/Dialect/LLVMIR/LLVMDialect.h>
|
||||
|
@ -34,6 +35,27 @@
|
|||
#include <cstdint>
|
||||
|
||||
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
|
||||
|
@ -191,4 +213,6 @@ void SLIRToMLIRPass::runOnModule() {
|
|||
std::unique_ptr<mlir::Pass> createSLIRLowerToMLIRPass() {
|
||||
return std::make_unique<SLIRToMLIRPass>();
|
||||
};
|
||||
|
||||
void registerAllPasses() { registerPasses(); }
|
||||
} // namespace serene::passes
|
||||
|
|
|
@ -24,4 +24,16 @@
|
|||
#include <mlir/IR/BuiltinAttributes.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