Compare commits
3 Commits
Author | SHA1 | Date |
---|---|---|
Sameer Rahmani | 1345552d27 | |
Sameer Rahmani | 664772f456 | |
Sameer Rahmani | e69ee4dc8f |
|
@ -170,7 +170,8 @@ CLOSED: [2021-09-04 Sat 10:53]
|
||||||
*** The owner of LLVM/MLIR contexts
|
*** The owner of LLVM/MLIR contexts
|
||||||
*** Holds the namespace table
|
*** Holds the namespace table
|
||||||
*** Probably will contain the primitive types as well
|
*** Probably will contain the primitive types as well
|
||||||
* Episode 8 - MLIR Basics
|
* DONE Episode 8 - MLIR Basics
|
||||||
|
CLOSED: [2021-09-17 Fri 10:18]
|
||||||
** Serene Changes
|
** Serene Changes
|
||||||
- Introducing a SourceManager
|
- Introducing a SourceManager
|
||||||
- Reader changes
|
- Reader changes
|
||||||
|
@ -375,3 +376,29 @@ define i64 @main1(i64 %0, i64 %1, i64 %2) !dbg !9 {
|
||||||
- https://mlir.llvm.org/docs
|
- https://mlir.llvm.org/docs
|
||||||
- https://mlir.llvm.org/docs/LangRef
|
- https://mlir.llvm.org/docs/LangRef
|
||||||
- https://en.wikipedia.org/wiki/Basic_block
|
- https://en.wikipedia.org/wiki/Basic_block
|
||||||
|
|
||||||
|
* Episode 9 - IR (SLIR) generation
|
||||||
|
** Updates:
|
||||||
|
- Source manager
|
||||||
|
- Diagnostic Engine
|
||||||
|
- JIT
|
||||||
|
|
||||||
|
There will be an episode dedicated to eache of these
|
||||||
|
** How does IR generation works
|
||||||
|
- Pass around MLIR context
|
||||||
|
- Create Builder objects that creates operations in specific
|
||||||
|
locations
|
||||||
|
- ModuleOp
|
||||||
|
- Namespace
|
||||||
|
** How to define a new dialect
|
||||||
|
- Pure C++
|
||||||
|
- Tablegen
|
||||||
|
** SLIR
|
||||||
|
*** The SLIR goal
|
||||||
|
- An IR that follows the AST
|
||||||
|
- Rename?
|
||||||
|
*** Steps
|
||||||
|
- [X] Define the new dialect
|
||||||
|
- [X] Setup the tablegen
|
||||||
|
- [X] Define the operations
|
||||||
|
- [X] Walk the AST and generate the operations
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
set(LLVM_TARGET_DEFINITIONS dialect.td)
|
set(LLVM_TARGET_DEFINITIONS dialect.td)
|
||||||
|
|
||||||
mlir_tablegen(ops.h.inc -gen-op-decls)
|
mlir_tablegen(ops.h.inc -gen-op-decls)
|
||||||
mlir_tablegen(ops.cpp.inc -gen-op-defs)
|
mlir_tablegen(ops.cpp.inc -gen-op-defs)
|
||||||
mlir_tablegen(dialect.h.inc -gen-dialect-decls)
|
mlir_tablegen(dialect.h.inc -gen-dialect-decls)
|
||||||
mlir_tablegen(dialect.cpp.inc -gen-dialect-defs)
|
mlir_tablegen(dialect.cpp.inc -gen-dialect-defs)
|
||||||
|
|
||||||
add_public_tablegen_target(SereneDialectGen)
|
add_public_tablegen_target(SereneDialectGen)
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "mlir/IR/BuiltinOps.h"
|
#include "mlir/IR/BuiltinOps.h"
|
||||||
#include "mlir/IR/Dialect.h"
|
#include "mlir/IR/Dialect.h"
|
||||||
#include "mlir/Interfaces/SideEffectInterfaces.h"
|
#include "mlir/Interfaces/SideEffectInterfaces.h"
|
||||||
|
#include "mlir/Interfaces/ControlFlowInterfaces.h"
|
||||||
|
|
||||||
// Include the auto-generated header file containing the declaration of the
|
// Include the auto-generated header file containing the declaration of the
|
||||||
// serene's dialect.
|
// serene's dialect.
|
||||||
|
|
|
@ -2,10 +2,15 @@
|
||||||
#define SERENE_DIALECT
|
#define SERENE_DIALECT
|
||||||
|
|
||||||
include "mlir/IR/OpBase.td"
|
include "mlir/IR/OpBase.td"
|
||||||
|
include "mlir/IR/OpAsmInterface.td"
|
||||||
|
include "mlir/IR/SymbolInterfaces.td"
|
||||||
include "mlir/Interfaces/SideEffectInterfaces.td"
|
include "mlir/Interfaces/SideEffectInterfaces.td"
|
||||||
include "mlir/Interfaces/CallInterfaces.td"
|
include "mlir/Interfaces/CallInterfaces.td"
|
||||||
include "mlir/Interfaces/CastInterfaces.td"
|
include "mlir/Interfaces/CastInterfaces.td"
|
||||||
|
include "mlir/Interfaces/SideEffectInterfaces.td"
|
||||||
|
include "mlir/Interfaces/ControlFlowInterfaces.td"
|
||||||
include "mlir/Interfaces/DataLayoutInterfaces.td"
|
include "mlir/Interfaces/DataLayoutInterfaces.td"
|
||||||
|
include "mlir/Interfaces/VectorInterfaces.td"
|
||||||
|
|
||||||
|
|
||||||
// Dialect definition. It will directly generate the SereneDialect class
|
// Dialect definition. It will directly generate the SereneDialect class
|
||||||
|
@ -32,49 +37,17 @@ class Serene_Op<string mnemonic, list<OpTrait> traits = []> :
|
||||||
class Serene_Type<string name> : TypeDef<Serene_Dialect, name> { }
|
class Serene_Type<string name> : TypeDef<Serene_Dialect, name> { }
|
||||||
|
|
||||||
|
|
||||||
// def SymbolType : Serene_Type<"Symbol"> {
|
|
||||||
|
|
||||||
// let mnemonic = "symbol";
|
|
||||||
|
|
||||||
// let summary = "A typical Lisp symbol";
|
|
||||||
|
|
||||||
// let description = [{
|
|
||||||
// A symbol is just a name and nothing more. Just a name
|
|
||||||
// to give to a value or to use it as it is.
|
|
||||||
// }];
|
|
||||||
|
|
||||||
// // let cppNamespace = "::serene::sir";
|
|
||||||
// let parameters = (ins "std::string":$name);
|
|
||||||
|
|
||||||
// // We define the printer inline.
|
|
||||||
// let printer = [{
|
|
||||||
// $_printer << "Symbol<" << getImpl()->name << ">";
|
|
||||||
// }];
|
|
||||||
|
|
||||||
// // The parser is defined here also.
|
|
||||||
// let parser = [{
|
|
||||||
// if ($_parser.parseLess())
|
|
||||||
// return Type();
|
|
||||||
|
|
||||||
// std::string name;
|
|
||||||
// if ($_parser.parseInteger(name))
|
|
||||||
// return Type();
|
|
||||||
|
|
||||||
// return get($_ctxt, name);
|
|
||||||
// }];
|
|
||||||
// }
|
|
||||||
|
|
||||||
def ValueOp: Serene_Op<"value"> {
|
def ValueOp: Serene_Op<"value"> {
|
||||||
|
|
||||||
let summary = "This operation represent a value";
|
let summary = "This operation represent a value";
|
||||||
let description = [{
|
let description = [{
|
||||||
some description
|
ValueOp
|
||||||
}];
|
}];
|
||||||
|
|
||||||
let arguments = (ins I64Attr:$value);
|
let arguments = (ins I64Attr:$value);
|
||||||
let results = (outs I64);
|
let results = (outs I64);
|
||||||
|
|
||||||
// let verifier = [{ return serene::sir::verify(*this); }];
|
//let verifier = [{ return serene::sir::verify(*this); }];
|
||||||
|
|
||||||
let builders = [
|
let builders = [
|
||||||
OpBuilder<(ins "int":$value), [{
|
OpBuilder<(ins "int":$value), [{
|
||||||
|
@ -85,9 +58,12 @@ def ValueOp: Serene_Op<"value"> {
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: Add the FunctionLike trait here and include its header file in dialect.h
|
||||||
def FnOp: Serene_Op<"fn", [
|
def FnOp: Serene_Op<"fn", [
|
||||||
AffineScope, AutomaticAllocationScope,
|
AffineScope, AutomaticAllocationScope,
|
||||||
IsolatedFromAbove
|
IsolatedFromAbove,
|
||||||
]> {
|
]> {
|
||||||
|
|
||||||
let summary = "This operation is just a place holder for a function";
|
let summary = "This operation is just a place holder for a function";
|
||||||
|
@ -102,23 +78,21 @@ def FnOp: Serene_Op<"fn", [
|
||||||
OptionalAttr<StrAttr>:$sym_visibility);
|
OptionalAttr<StrAttr>:$sym_visibility);
|
||||||
|
|
||||||
let regions = (region AnyRegion:$body);
|
let regions = (region AnyRegion:$body);
|
||||||
let results = (outs NoneType);
|
let results = (outs I64);
|
||||||
|
|
||||||
// let builders = [
|
|
||||||
// OpBuilder<(ins
|
|
||||||
// "llvm::StringRef":$name, "mlir::FunctionType":$type,
|
|
||||||
// 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);
|
|
||||||
// }];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def ReturnOp: Serene_Op<"return", [NoSideEffect, HasParent<"FnOp">,
|
||||||
|
ReturnLike, Terminator]> {
|
||||||
|
|
||||||
|
let summary = "This operation marks the return value of a function";
|
||||||
|
let description = [{
|
||||||
|
ReturnOp
|
||||||
|
}];
|
||||||
|
|
||||||
|
let arguments = (ins AnyType:$operand);
|
||||||
|
let assemblyFormat =
|
||||||
|
[{ attr-dict $operand `:` type($operand) }];
|
||||||
|
}
|
||||||
|
|
||||||
#endif // SERENE_DIALECT
|
#endif // SERENE_DIALECT
|
||||||
|
|
|
@ -127,29 +127,34 @@ void Fn::generateIR(serene::Namespace &ns, mlir::ModuleOp &m) {
|
||||||
argSym->name, mlir::TypeAttr::get(builder.getI64Type())));
|
argSym->name, mlir::TypeAttr::get(builder.getI64Type())));
|
||||||
}
|
}
|
||||||
|
|
||||||
// auto funcType = builder.getFunctionType(arg_types, builder.getI64Type());
|
|
||||||
auto fn = builder.create<slir::FnOp>(
|
auto fn = builder.create<slir::FnOp>(
|
||||||
loc, builder.getI64Type(), name,
|
loc, builder.getI64Type(), name,
|
||||||
mlir::DictionaryAttr::get(builder.getContext(), arguments),
|
mlir::DictionaryAttr::get(builder.getContext(), arguments),
|
||||||
builder.getStringAttr("public"));
|
builder.getStringAttr("public"));
|
||||||
|
|
||||||
|
|
||||||
if (!fn) {
|
if (!fn) {
|
||||||
m.emitError(llvm::formatv("Can't create the function '{0}'", name));
|
m.emitError(llvm::formatv("Can't create the function '{0}'", name));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto *entryBlock = new mlir::Block();
|
|
||||||
auto &body = fn.body();
|
auto &body = fn.body();
|
||||||
|
auto *entryBlock = new mlir::Block();
|
||||||
|
|
||||||
body.push_back(entryBlock);
|
body.push_back(entryBlock);
|
||||||
|
|
||||||
builder.setInsertionPointToStart(entryBlock);
|
builder.setInsertionPointToStart(entryBlock);
|
||||||
auto retVal = builder.create<slir::ValueOp>(loc, 0).getResult();
|
auto retVal = builder.create<slir::ValueOp>(loc, 0).getResult();
|
||||||
|
|
||||||
mlir::ReturnOp returnOp = builder.create<mlir::ReturnOp>(loc, retVal);
|
slir::ReturnOp returnOp = builder.create<slir::ReturnOp>(loc, retVal);
|
||||||
|
|
||||||
if (!returnOp) {
|
if (!returnOp) {
|
||||||
m.emitError(
|
m.emitError(
|
||||||
llvm::formatv("Can't create the return value of function '{0}'", name));
|
llvm::formatv("Can't create the return value of function '{0}'", name));
|
||||||
|
fn.erase();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m.push_back(fn);
|
m.push_back(fn);
|
||||||
};
|
};
|
||||||
} // namespace exprs
|
} // namespace exprs
|
||||||
|
|
|
@ -24,12 +24,14 @@
|
||||||
|
|
||||||
#include "serene/namespace.h"
|
#include "serene/namespace.h"
|
||||||
|
|
||||||
|
#include "mlir/IR/OperationSupport.h"
|
||||||
#include "serene/context.h"
|
#include "serene/context.h"
|
||||||
#include "serene/errors/constants.h"
|
#include "serene/errors/constants.h"
|
||||||
#include "serene/exprs/expression.h"
|
#include "serene/exprs/expression.h"
|
||||||
#include "serene/llvm/IR/Value.h"
|
#include "serene/llvm/IR/Value.h"
|
||||||
#include "serene/slir/slir.h"
|
#include "serene/slir/slir.h"
|
||||||
|
|
||||||
|
#include <mlir/IR/Verifier.h>
|
||||||
#include <llvm/ADT/StringRef.h>
|
#include <llvm/ADT/StringRef.h>
|
||||||
#include <llvm/Support/FormatVariadic.h>
|
#include <llvm/Support/FormatVariadic.h>
|
||||||
#include <llvm/Support/raw_ostream.h>
|
#include <llvm/Support/raw_ostream.h>
|
||||||
|
@ -81,6 +83,12 @@ MaybeModuleOp Namespace::generate() {
|
||||||
x->generateIR(*this, module);
|
x->generateIR(*this, module);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(mlir::failed(mlir::verify(module))) {
|
||||||
|
module.emitError("Can't verify the module");
|
||||||
|
module.erase();
|
||||||
|
return MaybeModuleOp::error(true);
|
||||||
|
}
|
||||||
|
|
||||||
if (mlir::failed(runPasses(module))) {
|
if (mlir::failed(runPasses(module))) {
|
||||||
// TODO: throw a proper errer
|
// TODO: throw a proper errer
|
||||||
module.emitError("Failure in passes!");
|
module.emitError("Failure in passes!");
|
||||||
|
@ -103,7 +111,10 @@ void Namespace::dump() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
maybeModuleOp.getValue()->dump();
|
mlir::OpPrintingFlags flags;
|
||||||
|
flags.enableDebugInfo();
|
||||||
|
|
||||||
|
maybeModuleOp.getValue()->print(llvm::outs(), flags);
|
||||||
};
|
};
|
||||||
|
|
||||||
MaybeModule Namespace::compileToLLVM() {
|
MaybeModule Namespace::compileToLLVM() {
|
||||||
|
@ -122,7 +133,7 @@ MaybeModule Namespace::compileToLLVM() {
|
||||||
return MaybeModule::error(true);
|
return MaybeModule::error(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
Namespace::~Namespace(){};
|
Namespace::~Namespace(){};
|
||||||
|
|
||||||
std::shared_ptr<Namespace>
|
std::shared_ptr<Namespace>
|
||||||
makeNamespace(SereneContext &ctx, llvm::StringRef name,
|
makeNamespace(SereneContext &ctx, llvm::StringRef name,
|
||||||
|
|
Loading…
Reference in New Issue