Add a very basic 'fn' operator to slir

This commit is contained in:
Sameer Rahmani 2021-06-23 20:34:57 +01:00
parent 7f7f49d3ac
commit 098365425d
10 changed files with 141 additions and 20 deletions

View File

@ -1 +1 @@
4 (def main (fn () 3))

View File

@ -32,6 +32,7 @@
#include <llvm/ADT/StringRef.h> #include <llvm/ADT/StringRef.h>
#include <memory> #include <memory>
#include <mlir/Dialect/StandardOps/IR/Ops.h>
#include <mlir/IR/MLIRContext.h> #include <mlir/IR/MLIRContext.h>
#include <mlir/Pass/PassManager.h> #include <mlir/Pass/PassManager.h>
@ -82,6 +83,7 @@ public:
SereneContext() SereneContext()
: pm(&mlirContext), targetPhase(CompilationPhase::NoOptimization) { : pm(&mlirContext), targetPhase(CompilationPhase::NoOptimization) {
mlirContext.getOrLoadDialect<serene::slir::SereneDialect>(); mlirContext.getOrLoadDialect<serene::slir::SereneDialect>();
mlirContext.getOrLoadDialect<mlir::StandardOpsDialect>();
pm.enableCrashReproducerGeneration("/home/lxsameer/mlir.mlir"); pm.enableCrashReproducerGeneration("/home/lxsameer/mlir.mlir");
}; };

View File

@ -56,7 +56,7 @@ public:
ExprType getType() const; ExprType getType() const;
std::string toString() const; std::string toString() const;
MaybeNode analyze(SereneContext &); MaybeNode analyze(SereneContext &);
void generateIR(serene::Namespace &){}; void generateIR(serene::Namespace &);
static bool classof(const Expression *e); static bool classof(const Expression *e);

View File

@ -60,7 +60,7 @@ public:
ExprType getType() const; ExprType getType() const;
std::string toString() const; std::string toString() const;
MaybeNode analyze(SereneContext &); MaybeNode analyze(SereneContext &);
void generateIR(serene::Namespace &){}; void generateIR(serene::Namespace &);
static bool classof(const Expression *e); static bool classof(const Expression *e);

View File

@ -3,6 +3,9 @@
include "mlir/IR/OpBase.td" include "mlir/IR/OpBase.td"
include "mlir/Interfaces/SideEffectInterfaces.td" include "mlir/Interfaces/SideEffectInterfaces.td"
include "mlir/Interfaces/CallInterfaces.td"
include "mlir/Interfaces/CastInterfaces.td"
include "mlir/Interfaces/DataLayoutInterfaces.td"
// Dialect definition. It will directly generate the SereneDialect class // Dialect definition. It will directly generate the SereneDialect class
@ -82,23 +85,40 @@ def ValueOp: Serene_Op<"value"> {
]; ];
} }
def FnIdOp: Serene_Op<"fn_id"> { def FnOp: Serene_Op<"fn", [
AffineScope, AutomaticAllocationScope,
IsolatedFromAbove
]> {
let summary = "This operation is just a place holder for an anonymouse function"; let summary = "This operation is just a place holder for a function";
let description = [{ let description = [{
s A place holder for an anonymous function. For example consider an expression A place holder for an anonymous function. For example consider an expression
like `(def a (fn (x) x))`, in this case we don't immediately create an anonymous like `(def a (fn (x) x))`, in this case we don't immediately create an anonymous
function since we need to set the name and create the function later. function since we need to set the name and create the function later.
}]; }];
let arguments = (ins StrAttr:$name); let arguments = (ins StrAttr:$name,
TypeAttr:$type,
OptionalAttr<StrAttr>:$sym_visibility);
let regions = (region AnyRegion:$body);
let results = (outs NoneType); let results = (outs NoneType);
let builders = [ let builders = [
OpBuilder<(ins "std::string":$name), [{ OpBuilder<(ins
// Build from fix 64 bit int "llvm::StringRef":$name, "mlir::FunctionType":$type,
build(odsBuilder, odsState, odsBuilder.getNoneType(), odsBuilder.getStringAttr(name)); CArg<"llvm::ArrayRef<mlir::NamedAttribute>", "{}">:$attrs,
}]>, CArg<"llvm::ArrayRef<mlir::DictionaryAttr>", "{}">:$argAttrs)
]; >];
// let extraClassDeclaration = [{
// static FnOp create(mlir::Location location, llvm::StringRef name, mlir::FunctionType type,
// llvm::ArrayRef<mlir::NamedAttribute> attrs = {});
// static FnOp create(mlir::Location location, llvm::StringRef name, mlir::FunctionType type,
// mlir::Operation::dialect_attr_range attrs);
// static FnOp create(mlir::Location location, llvm::StringRef name, mlir::FunctionType type,
// llvm::ArrayRef<mlir::NamedAttribute> attrs,
// llvm::ArrayRef<mlir::DictionaryAttr> argAttrs);
// }];
} }
#endif // SERENE_DIALECT #endif // SERENE_DIALECT

View File

@ -65,7 +65,7 @@ add_library(serene
slir/value_op.cpp slir/value_op.cpp
slir/generatable.cpp slir/generatable.cpp
slir/utils.cpp slir/utils.cpp
slir/ops.cpp
passes/slir_lowering.cpp passes/slir_lowering.cpp
passes/to_llvm_dialect.cpp passes/to_llvm_dialect.cpp
${HEADER_LIST}) ${HEADER_LIST})

View File

@ -30,9 +30,9 @@
#include "serene/exprs/symbol.h" #include "serene/exprs/symbol.h"
#include "serene/exprs/traits.h" #include "serene/exprs/traits.h"
#include "llvm/Support/Casting.h" #include <llvm/Support/Casting.h>
#include "llvm/Support/ErrorHandling.h" #include <llvm/Support/ErrorHandling.h>
#include "llvm/Support/FormatVariadic.h" #include <llvm/Support/FormatVariadic.h>
namespace serene { namespace serene {
namespace exprs { namespace exprs {
@ -111,5 +111,14 @@ MaybeNode Def::make(SereneContext &ctx, List *list) {
llvm_unreachable("Inserting a value in the semantic env failed!"); llvm_unreachable("Inserting a value in the semantic env failed!");
} }
}; };
void Def::generateIR(serene::Namespace &ns) {
auto &module = ns.getModule();
if (value->getType() == ExprType::Fn) {
value->generateIR(ns);
return;
}
module.emitError("Def: not implemented!");
};
} // namespace exprs } // namespace exprs
} // namespace serene } // namespace serene

View File

@ -29,9 +29,13 @@
#include "serene/exprs/list.h" #include "serene/exprs/list.h"
#include "serene/exprs/symbol.h" #include "serene/exprs/symbol.h"
#include "serene/reader/semantics.h" #include "serene/reader/semantics.h"
#include "serene/slir/dialect.h"
#include "serene/slir/utils.h"
#include "llvm/Support/Casting.h" #include <cstdint>
#include "llvm/Support/FormatVariadic.h" #include <llvm/Support/Casting.h>
#include <llvm/Support/FormatVariadic.h>
#include <mlir/IR/Block.h>
namespace serene { namespace serene {
namespace exprs { namespace exprs {
@ -94,5 +98,41 @@ MaybeNode Fn::make(SereneContext &ctx, List *list) {
return makeSuccessfulNode<Fn>(ctx, list->location, *args, body); return makeSuccessfulNode<Fn>(ctx, list->location, *args, body);
}; };
void Fn::generateIR(serene::Namespace &ns) {
auto loc = slir::toMLIRLocation(ns, location.start);
auto &ctx = ns.getContext();
auto &module = ns.getModule();
mlir::OpBuilder builder(&ctx.mlirContext);
llvm::SmallVector<mlir::Type, 4> arg_types;
// at the moment we only support integers
for (size_t i = 0; i < args.count(); i++) {
arg_types.push_back(builder.getI64Type());
}
auto funcType = builder.getFunctionType(arg_types, builder.getI64Type());
auto fn = builder.create<slir::FnOp>(loc, name, funcType);
if (!fn) {
module.emitError(llvm::formatv("Can't create the function '{0}'", name));
}
auto *entryBlock = new mlir::Block();
auto &body = fn.body();
body.push_back(entryBlock);
builder.setInsertionPointToStart(entryBlock);
auto retVal = builder.create<slir::ValueOp>(loc, 0).getResult();
mlir::ReturnOp returnOp = builder.create<mlir::ReturnOp>(loc, retVal);
if (!returnOp) {
module.emitError(
llvm::formatv("Can't create the return value of function '{0}'", name));
return;
}
module.push_back(fn);
};
} // namespace exprs } // namespace exprs
} // namespace serene } // namespace serene

View File

@ -22,7 +22,6 @@
* SOFTWARE. * SOFTWARE.
*/ */
#include "mlir/Dialect/StandardOps/IR/Ops.h"
#include "serene/passes.h" #include "serene/passes.h"
#include "serene/slir/dialect.h" #include "serene/slir/dialect.h"
@ -31,6 +30,7 @@
#include <mlir/Dialect/Affine/IR/AffineOps.h> #include <mlir/Dialect/Affine/IR/AffineOps.h>
#include <mlir/Dialect/LLVMIR/LLVMDialect.h> #include <mlir/Dialect/LLVMIR/LLVMDialect.h>
#include <mlir/Dialect/MemRef/IR/MemRef.h> #include <mlir/Dialect/MemRef/IR/MemRef.h>
#include <mlir/Dialect/StandardOps/IR/Ops.h>
#include <mlir/IR/BuiltinOps.h> #include <mlir/IR/BuiltinOps.h>
#include <mlir/Pass/Pass.h> #include <mlir/Pass/Pass.h>
#include <mlir/Transforms/DialectConversion.h> #include <mlir/Transforms/DialectConversion.h>

50
src/serene/slir/ops.cpp Normal file
View File

@ -0,0 +1,50 @@
/*
* Serene programming language.
*
* Copyright (c) 2019-2021 Sameer Rahmani <lxsameer@gnu.org>
*
* 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/slir/dialect.h"
#include <llvm/Support/FormatVariadic.h>
#include <mlir/IR/Builders.h>
#include <mlir/IR/OperationSupport.h>
namespace serene::slir {
void FnOp::build(mlir::OpBuilder &odsBuilder, mlir::OperationState &odsState,
llvm::StringRef name, mlir::FunctionType type,
llvm::ArrayRef<mlir::NamedAttribute> attrs,
llvm::ArrayRef<mlir::DictionaryAttr> argAttrs) {
odsState.addAttribute("name", odsBuilder.getStringAttr(name));
for (unsigned int i = 0; i <= type.getNumInputs(); i++) {
std::string attrName = llvm::formatv("input_type{0}", i);
odsState.addAttribute(attrName, mlir::TypeAttr::get(type.getResult(i)));
}
// if (sym_visibility) {
// odsState.addAttribute("sym_visibility", sym_visibility);
// }
(void)odsState.addRegion();
odsState.addTypes(type);
};
} // namespace serene::slir