Add the IR generation facilities to Namespace and Expression
This commit is contained in:
parent
7e319ece13
commit
65b6aa4020
|
@ -0,0 +1 @@
|
|||
#leak:mlir::Region::emplaceBlock
|
|
@ -27,6 +27,7 @@
|
|||
#include "serene/namespace.h"
|
||||
#include "serene/reader/reader.h"
|
||||
#include "serene/reader/semantics.h"
|
||||
#include "serene/slir/generatable.h"
|
||||
#include "serene/slir/slir.h"
|
||||
#include <iostream>
|
||||
#include <llvm/Support/CommandLine.h>
|
||||
|
@ -37,7 +38,7 @@ using namespace serene;
|
|||
namespace cl = llvm::cl;
|
||||
|
||||
namespace {
|
||||
enum Action { None, DumpAST, DumpIR, DumpSemantic };
|
||||
enum Action { None, DumpAST, DumpIR, DumpSLIR, DumpSemantic };
|
||||
}
|
||||
|
||||
static cl::opt<std::string> inputFile(cl::Positional,
|
||||
|
@ -49,7 +50,8 @@ static cl::opt<enum Action> emitAction(
|
|||
"emit", cl::desc("Select what to dump."),
|
||||
cl::values(clEnumValN(DumpSemantic, "ast1",
|
||||
"Output the AST after one level of analysis only")),
|
||||
cl::values(clEnumValN(DumpIR, "slir", "Output the SLIR only")),
|
||||
cl::values(clEnumValN(DumpIR, "ir", "Output the lowered IR only")),
|
||||
cl::values(clEnumValN(DumpSLIR, "slir", "Output the SLIR only")),
|
||||
cl::values(clEnumValN(DumpAST, "ast", "Output the AST only"))
|
||||
|
||||
);
|
||||
|
@ -112,7 +114,12 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
if (isSet.succeeded()) {
|
||||
ctx->insertNS(ns);
|
||||
serene::slir::dumpSLIR(*ctx, ns->name);
|
||||
serene::slir::dumpIR<Namespace>(*ns);
|
||||
// if (mlir::failed(ns->generateIR(*ctx))) {
|
||||
// // TODO: Replace with an actual error
|
||||
// llvm::outs() << "Can't generate IR for namespace\n";
|
||||
// }
|
||||
// serene::slir::dumpSLIR(*ctx, ns->name);
|
||||
} else {
|
||||
llvm::outs() << "Can't set the tree of the namespace!\n";
|
||||
}
|
||||
|
|
5
builder
5
builder
|
@ -6,6 +6,9 @@ command=$1
|
|||
export CC=$(which clang)
|
||||
export CXX=$(which clang++)
|
||||
export LDFLAGS="-fuse-ld=lld"
|
||||
|
||||
export ASAN_OPTIONS=check_initialization_order=1
|
||||
export LSAN_OPTIONS=suppressions=`pwd`/.ignore_sanitize
|
||||
ROOT_DIR=`pwd`
|
||||
BUILD_DIR=$ROOT_DIR/build
|
||||
|
||||
|
@ -21,7 +24,7 @@ function popd_build() {
|
|||
|
||||
function compile() {
|
||||
pushed_build
|
||||
ninja
|
||||
ninja -j `nproc`
|
||||
popd_build
|
||||
}
|
||||
|
||||
|
|
|
@ -55,6 +55,7 @@ public:
|
|||
ExprType getType() const;
|
||||
std::string toString() const;
|
||||
MaybeNode analyze(SereneContext &);
|
||||
void generateIR(serene::Namespace &){};
|
||||
|
||||
static bool classof(const Expression *e);
|
||||
|
||||
|
|
|
@ -54,6 +54,7 @@ public:
|
|||
ExprType getType() const;
|
||||
std::string toString() const;
|
||||
MaybeNode analyze(SereneContext &);
|
||||
void generateIR(serene::Namespace &){};
|
||||
|
||||
static bool classof(const Expression *e);
|
||||
|
||||
|
|
|
@ -34,10 +34,6 @@
|
|||
|
||||
namespace serene {
|
||||
|
||||
namespace reader {
|
||||
class SereneContext;
|
||||
}
|
||||
|
||||
/// Contains all the builtin AST expressions including those which do not appear
|
||||
/// in the syntax directly. Like function definitions.
|
||||
namespace exprs {
|
||||
|
@ -82,6 +78,8 @@ public:
|
|||
///
|
||||
/// \param ctx is the context object of the semantic analyzer.
|
||||
virtual MaybeNode analyze(SereneContext &ctx) = 0;
|
||||
|
||||
virtual void generateIR(serene::Namespace &ns) = 0;
|
||||
};
|
||||
|
||||
/// Create a new `node` of type `T` and forwards any given parameter
|
||||
|
|
|
@ -58,6 +58,7 @@ public:
|
|||
ExprType getType() const;
|
||||
std::string toString() const;
|
||||
MaybeNode analyze(SereneContext &);
|
||||
void generateIR(serene::Namespace &){};
|
||||
|
||||
static bool classof(const Expression *e);
|
||||
|
||||
|
|
|
@ -67,6 +67,7 @@ public:
|
|||
std::vector<Node>::iterator end();
|
||||
|
||||
MaybeNode analyze(SereneContext &);
|
||||
void generateIR(serene::Namespace &){};
|
||||
|
||||
static bool classof(const Expression *e);
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include "serene/context.h"
|
||||
#include "serene/exprs/expression.h"
|
||||
#include "serene/namespace.h"
|
||||
#include "llvm/Support/FormatVariadic.h"
|
||||
|
||||
namespace serene {
|
||||
|
@ -57,6 +58,7 @@ struct Number : public Expression {
|
|||
// TODO: This is horrible, we need to fix it after the mvp
|
||||
int toI64();
|
||||
|
||||
void generateIR(serene::Namespace &);
|
||||
~Number() = default;
|
||||
};
|
||||
|
||||
|
|
|
@ -52,6 +52,7 @@ public:
|
|||
static bool classof(const Expression *e);
|
||||
|
||||
MaybeNode analyze(SereneContext &);
|
||||
void generateIR(serene::Namespace &){};
|
||||
|
||||
~Symbol() = default;
|
||||
};
|
||||
|
|
|
@ -22,16 +22,20 @@
|
|||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef NAMESPACE_H
|
||||
#define NAMESPACE_H
|
||||
#ifndef SERENE_NAMESPACE_H
|
||||
#define SERENE_NAMESPACE_H
|
||||
|
||||
#include "serene/environment.h"
|
||||
#include "serene/slir/generatable.h"
|
||||
#include "serene/traits.h"
|
||||
#include "serene/utils.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include <atomic>
|
||||
#include <llvm/ADT/SmallString.h>
|
||||
#include <llvm/ADT/StringRef.h>
|
||||
#include <llvm/IR/Module.h>
|
||||
#include <memory>
|
||||
#include <mlir/IR/Builders.h>
|
||||
#include <mlir/IR/BuiltinOps.h>
|
||||
#include <mlir/IR/Value.h>
|
||||
#include <mlir/Support/LogicalResult.h>
|
||||
#include <string>
|
||||
|
@ -51,26 +55,41 @@ using Ast = std::vector<Node>;
|
|||
/// Serene's namespaces are the unit of compilation. Any code that needs to be
|
||||
/// compiled has to be in a namespace. The official way to create a new
|
||||
/// namespace is to use the `makeNamespace` function.
|
||||
class Namespace {
|
||||
class Namespace : public WithTrait<Namespace, slir::Generatable> {
|
||||
private:
|
||||
SereneContext &ctx;
|
||||
bool initialized = false;
|
||||
std::atomic<uint> fn_counter = 0;
|
||||
exprs::Ast tree;
|
||||
mlir::OpBuilder builder;
|
||||
|
||||
public:
|
||||
mlir::StringRef name;
|
||||
llvm::Optional<std::string> filename;
|
||||
mlir::ModuleOp module;
|
||||
|
||||
/// The root environment of the namespace on the semantic analysis phase.
|
||||
/// Which is a mapping from names to AST nodes ( no evaluation ).
|
||||
Environment<std::string, exprs::Node> semanticEnv;
|
||||
|
||||
Environment<llvm::StringRef, mlir::Value> symbolTable;
|
||||
Namespace(llvm::StringRef ns_name, llvm::Optional<llvm::StringRef> filename);
|
||||
Namespace(SereneContext &ctx, llvm::StringRef ns_name,
|
||||
llvm::Optional<llvm::StringRef> filename);
|
||||
|
||||
exprs::Ast &getTree();
|
||||
mlir::LogicalResult setTree(exprs::Ast &);
|
||||
uint nextFnCounter();
|
||||
|
||||
mlir::OpBuilder &getBuilder();
|
||||
mlir::ModuleOp &getModule();
|
||||
SereneContext &getContext();
|
||||
|
||||
// Generatable Trait
|
||||
mlir::ModuleOp &generate();
|
||||
mlir::LogicalResult runPasses();
|
||||
void dumpSLIR();
|
||||
void dumpToIR();
|
||||
|
||||
~Namespace();
|
||||
};
|
||||
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
set(LLVM_TARGET_DEFINITIONS dialect.td)
|
||||
mlir_tablegen(ops.hpp.inc -gen-op-decls)
|
||||
mlir_tablegen(ops.cpp.inc -gen-op-defs)
|
||||
mlir_tablegen(dialect.hpp.inc -gen-dialect-decls)
|
||||
add_public_tablegen_target(SereneDialectGen)
|
|
@ -1,104 +0,0 @@
|
|||
#ifndef SERENE_DIALECT
|
||||
#define SERENE_DIALECT
|
||||
|
||||
include "mlir/IR/OpBase.td"
|
||||
include "mlir/Interfaces/SideEffectInterfaces.td"
|
||||
|
||||
|
||||
// Dialect definition. It will directly generate the SereneDialect class
|
||||
def Serene_Dialect : Dialect {
|
||||
let name = "serene";
|
||||
let cppNamespace = "::serene::sir";
|
||||
let summary = "Primary IR of serene language.";
|
||||
let description = [{
|
||||
This dialect tries to map the special forms of a lisp into
|
||||
IR level operations.
|
||||
}];
|
||||
}
|
||||
|
||||
// Base class for Serene dialect operations. This operation inherits from the base
|
||||
// `Op` class in OpBase.td, and provides:
|
||||
// * The parent dialect of the operation.
|
||||
// * The mnemonic for the operation, or the name without the dialect prefix.
|
||||
// * A list of traits for the operation.
|
||||
class Serene_Op<string mnemonic, list<OpTrait> traits = []> :
|
||||
Op<Serene_Dialect, mnemonic, traits>;
|
||||
|
||||
|
||||
// All of the types will extend this class.
|
||||
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"> {
|
||||
|
||||
let summary = "This operation represent a value";
|
||||
let description = [{
|
||||
some description
|
||||
}];
|
||||
|
||||
let arguments = (ins I64Attr:$value);
|
||||
let results = (outs I64);
|
||||
|
||||
// let verifier = [{ return serene::sir::verify(*this); }];
|
||||
|
||||
let builders = [
|
||||
OpBuilder<(ins "int":$value), [{
|
||||
// Build from fix 64 bit int
|
||||
build(odsBuilder, odsState, odsBuilder.getI64Type(), (uint64_t) value);
|
||||
}]>,
|
||||
|
||||
];
|
||||
}
|
||||
|
||||
def FnIdOp: Serene_Op<"fn_id"> {
|
||||
|
||||
let summary = "This operation is just a place holder for an anonymouse function";
|
||||
let description = [{
|
||||
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
|
||||
function since we need to set the name and create the function later.
|
||||
}];
|
||||
|
||||
let arguments = (ins StrAttr:$name);
|
||||
let results = (outs NoneType);
|
||||
|
||||
let builders = [
|
||||
OpBuilder<(ins "std::string":$name), [{
|
||||
// Build from fix 64 bit int
|
||||
build(odsBuilder, odsState, odsBuilder.getNoneType(), odsBuilder.getStringAttr(name));
|
||||
}]>,
|
||||
];
|
||||
}
|
||||
#endif // SERENE_DIALECT
|
|
@ -1,79 +0,0 @@
|
|||
/**
|
||||
* Serene programming language.
|
||||
*
|
||||
* Copyright (c) 2020 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.
|
||||
*/
|
||||
#ifndef GENERATOR_H
|
||||
#define GENERATOR_H
|
||||
|
||||
#include "mlir/IR/Builders.h"
|
||||
#include "mlir/IR/BuiltinOps.h"
|
||||
#include "mlir/IR/Identifier.h"
|
||||
#include "mlir/IR/MLIRContext.h"
|
||||
#include "serene/expr.hpp"
|
||||
#include "serene/list.hpp"
|
||||
#include "serene/namespace.h"
|
||||
#include "serene/number.hpp"
|
||||
#include "serene/symbol.hpp"
|
||||
#include "llvm/ADT/ScopedHashTable.h"
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
namespace serene {
|
||||
namespace sir {
|
||||
|
||||
using FnIdPair = std::pair<mlir::Identifier, mlir::FuncOp>;
|
||||
|
||||
class Generator {
|
||||
private:
|
||||
::mlir::OpBuilder builder;
|
||||
::mlir::ModuleOp module;
|
||||
std::unique_ptr<::serene::Namespace> ns;
|
||||
std::atomic_int anonymousFnCounter{1};
|
||||
llvm::DenseMap<mlir::Identifier, mlir::FuncOp> anonymousFunctions;
|
||||
llvm::ScopedHashTable<llvm::StringRef, mlir::Value> symbolTable;
|
||||
|
||||
// TODO: Should we use builder here? maybe there is a better option
|
||||
::mlir::Location toMLIRLocation(serene::reader::Location *);
|
||||
|
||||
// mlir::FuncOp generateFn(serene::reader::Location, std::string, List *,
|
||||
// List *);
|
||||
|
||||
public:
|
||||
Generator(mlir::MLIRContext &context, ::serene::Namespace *ns)
|
||||
: builder(&context),
|
||||
module(mlir::ModuleOp::create(builder.getUnknownLoc(), ns->name)) {
|
||||
this->ns.reset(ns);
|
||||
}
|
||||
|
||||
mlir::Operation *generate(Number *);
|
||||
mlir::Operation *generate(AExpr *);
|
||||
mlir::Value generate(List *);
|
||||
mlir::ModuleOp generate();
|
||||
~Generator();
|
||||
};
|
||||
|
||||
} // namespace sir
|
||||
|
||||
} // namespace serene
|
||||
|
||||
#endif
|
|
@ -22,50 +22,50 @@
|
|||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef GENERATOR_H
|
||||
#define GENERATOR_H
|
||||
#ifndef SERENE_SLIR_GENERATABLE_H
|
||||
#define SERENE_SLIR_GENERATABLE_H
|
||||
|
||||
#include "mlir/IR/Builders.h"
|
||||
#include "mlir/IR/BuiltinOps.h"
|
||||
#include "mlir/IR/Identifier.h"
|
||||
#include "serene/context.h"
|
||||
#include "serene/exprs/expression.h"
|
||||
#include "serene/exprs/list.h"
|
||||
#include "serene/exprs/number.h"
|
||||
#include "serene/exprs/symbol.h"
|
||||
#include "serene/namespace.h"
|
||||
#include "llvm/ADT/ScopedHashTable.h"
|
||||
#include <memory>
|
||||
#include "serene/reader/location.h"
|
||||
#include "serene/traits.h"
|
||||
#include <utility>
|
||||
|
||||
namespace serene {
|
||||
class Namespace;
|
||||
}
|
||||
|
||||
namespace serene::slir {
|
||||
|
||||
class Generator {
|
||||
private:
|
||||
serene::SereneContext &ctx;
|
||||
mlir::OpBuilder builder;
|
||||
mlir::ModuleOp module;
|
||||
std::shared_ptr<serene::Namespace> ns;
|
||||
|
||||
// TODO: Should we use builder here? maybe there is a better option
|
||||
mlir::Location toMLIRLocation(serene::reader::Location &);
|
||||
|
||||
template <typename T>
|
||||
class GeneratableUnit : public TraitBase<T, GeneratableUnit> {
|
||||
public:
|
||||
Generator(serene::SereneContext &ctx, llvm::StringRef ns_name)
|
||||
: ctx(ctx), builder(&ctx.mlirContext),
|
||||
module(mlir::ModuleOp::create(builder.getUnknownLoc(), ns_name)) {
|
||||
this->ns = ctx.getNS(ns_name);
|
||||
GeneratableUnit(){};
|
||||
GeneratableUnit(const GeneratableUnit &) = delete;
|
||||
|
||||
void generate(serene::Namespace &ns) {
|
||||
// TODO: should we return any status or possible error here or
|
||||
// should we just populate them in a ns wide state?
|
||||
this->Object().generateIR(ns);
|
||||
};
|
||||
|
||||
void generate(exprs::Number &);
|
||||
mlir::Operation *generate(exprs::Expression *);
|
||||
mlir::Value generate(exprs::List *);
|
||||
mlir::ModuleOp generate();
|
||||
|
||||
serene::Namespace &getNs();
|
||||
~Generator();
|
||||
};
|
||||
|
||||
template <typename T> class Generatable : public TraitBase<T, Generatable> {
|
||||
public:
|
||||
Generatable(){};
|
||||
Generatable(const Generatable &) = delete;
|
||||
|
||||
mlir::ModuleOp &generate();
|
||||
mlir::LogicalResult runPasses();
|
||||
void dumpSLIR();
|
||||
void dumpIR() { this->Object().dumpToIR(); };
|
||||
};
|
||||
|
||||
template <typename T> void dumpIR(Generatable<T> &t) { t.dumpIR(); };
|
||||
|
||||
template <typename T> void dumpSLIR(Generatable<T> &t) { t.dumpSLIR(); };
|
||||
|
||||
} // namespace serene::slir
|
||||
|
||||
#endif
|
|
@ -27,28 +27,11 @@
|
|||
#include "mlir/IR/BuiltinOps.h"
|
||||
#include "mlir/IR/MLIRContext.h"
|
||||
#include "serene/exprs/expression.h"
|
||||
#include "serene/namespace.h"
|
||||
#include "serene/slir/generator.h"
|
||||
#include "serene/slir/generatable.h"
|
||||
#include <memory>
|
||||
|
||||
namespace serene {
|
||||
namespace slir {
|
||||
|
||||
class SLIR {
|
||||
|
||||
private:
|
||||
serene::SereneContext &context;
|
||||
|
||||
public:
|
||||
SLIR(serene::SereneContext &ctx);
|
||||
|
||||
mlir::OwningModuleRef generate(llvm::StringRef ns_name);
|
||||
|
||||
~SLIR();
|
||||
};
|
||||
|
||||
void dumpSLIR(serene::SereneContext &ctx, llvm::StringRef ns_name);
|
||||
} // namespace slir
|
||||
namespace slir {} // namespace slir
|
||||
|
||||
} // namespace serene
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/**
|
||||
/* -*- C++ -*-
|
||||
* Serene programming language.
|
||||
*
|
||||
* Copyright (c) 2020 Sameer Rahmani <lxsameer@gnu.org>
|
||||
* 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
|
||||
|
@ -21,34 +21,25 @@
|
|||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
#ifndef SIR_H
|
||||
#define SIR_H
|
||||
|
||||
#ifndef SERENE_SLIR_UTILS_H
|
||||
#define SERENE_SLIR_UTILS_H
|
||||
|
||||
#include "mlir/IR/BuiltinOps.h"
|
||||
#include "mlir/IR/MLIRContext.h"
|
||||
#include "serene/exprs/expression.h"
|
||||
#include "serene/sir/generator.hpp"
|
||||
#include <memory>
|
||||
#include "serene/reader/location.h"
|
||||
|
||||
namespace serene {
|
||||
namespace sir {
|
||||
class Namespace;
|
||||
}
|
||||
|
||||
class SIR {
|
||||
namespace serene::slir {
|
||||
|
||||
private:
|
||||
mlir::MLIRContext context;
|
||||
/**
|
||||
* Convert a Serene location to MLIR FileLineLoc Location
|
||||
*/
|
||||
::mlir::Location toMLIRLocation(serene::Namespace &,
|
||||
serene::reader::Location &);
|
||||
|
||||
public:
|
||||
SIR();
|
||||
|
||||
mlir::OwningModuleRef generate(serene::Namespace *ns);
|
||||
|
||||
~SIR();
|
||||
};
|
||||
|
||||
void dumpSIR(exprs::ast &t);
|
||||
} // namespace sir
|
||||
|
||||
} // namespace serene
|
||||
} // namespace serene::slir
|
||||
|
||||
#endif
|
|
@ -104,9 +104,11 @@ class TraitBase {
|
|||
protected:
|
||||
/// Statically casts the object to the concrete type object to be
|
||||
/// used in the Trait Types.
|
||||
const ConcreteType &Object() const {
|
||||
return static_cast<const ConcreteType &>(*this);
|
||||
};
|
||||
// const ConcreteType &Object() const {
|
||||
// return static_cast<const ConcreteType &>(*this);
|
||||
// };
|
||||
|
||||
ConcreteType &Object() { return static_cast<ConcreteType &>(*this); };
|
||||
};
|
||||
|
||||
template <typename ConcreteType>
|
||||
|
|
|
@ -30,7 +30,8 @@ set(HEADER_LIST
|
|||
|
||||
"${INCLUDE_DIR}/serene/slir/slir.h"
|
||||
"${INCLUDE_DIR}/serene/slir/dialect.h"
|
||||
"${INCLUDE_DIR}/serene/slir/generator.h"
|
||||
"${INCLUDE_DIR}/serene/slir/generatable.h"
|
||||
"${INCLUDE_DIR}/serene/slir/utils.h"
|
||||
"${INCLUDE_DIR}/serene/namespace.h"
|
||||
|
||||
"${INCLUDE_DIR}/serene/passes/slir_lowering.h")
|
||||
|
@ -60,10 +61,11 @@ add_library(serene
|
|||
errors/error.cpp
|
||||
|
||||
# IR
|
||||
slir/slir.cpp
|
||||
slir/dialect.cpp
|
||||
slir/value_op.cpp
|
||||
slir/generator.cpp
|
||||
slir/generatable.cpp
|
||||
slir/utils.cpp
|
||||
|
||||
passes/slir_lowering.cpp
|
||||
${HEADER_LIST})
|
||||
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
*/
|
||||
|
||||
#include "serene/exprs/number.h"
|
||||
#include "serene/slir/dialect.h"
|
||||
#include "serene/slir/utils.h"
|
||||
|
||||
namespace serene {
|
||||
namespace exprs {
|
||||
|
@ -44,5 +46,17 @@ bool Number::classof(const Expression *e) {
|
|||
|
||||
int Number::toI64() { return std::stoi(this->value); };
|
||||
|
||||
void Number::generateIR(serene::Namespace &ns) {
|
||||
mlir::OpBuilder &builder = ns.getBuilder();
|
||||
mlir::ModuleOp &module = ns.getModule();
|
||||
|
||||
auto op = builder.create<serene::slir::ValueOp>(
|
||||
serene::slir::toMLIRLocation(ns, location.start), toI64());
|
||||
|
||||
if (op) {
|
||||
module.push_back(op);
|
||||
}
|
||||
// TODO: in case of failure attach the error to the NS
|
||||
};
|
||||
} // namespace exprs
|
||||
} // namespace serene
|
||||
|
|
|
@ -23,10 +23,14 @@
|
|||
*/
|
||||
|
||||
#include "serene/namespace.h"
|
||||
#include "mlir/IR/BuiltinOps.h"
|
||||
#include "serene/context.h"
|
||||
#include "serene/exprs/expression.h"
|
||||
#include "serene/llvm/IR/Value.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Support/FormatVariadic.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
using namespace std;
|
||||
|
@ -34,9 +38,11 @@ using namespace llvm;
|
|||
|
||||
namespace serene {
|
||||
|
||||
Namespace::Namespace(llvm::StringRef ns_name,
|
||||
Namespace::Namespace(SereneContext &ctx, llvm::StringRef ns_name,
|
||||
llvm::Optional<llvm::StringRef> filename)
|
||||
: name(ns_name) {
|
||||
: ctx(ctx), builder(&ctx.mlirContext), name(ns_name),
|
||||
// TODO: Fix the unknown location by pointing to the `ns` form
|
||||
module(mlir::ModuleOp::create(builder.getUnknownLoc(), ns_name)) {
|
||||
if (filename.hasValue()) {
|
||||
this->filename.emplace(filename.getValue().str());
|
||||
}
|
||||
|
@ -56,15 +62,49 @@ mlir::LogicalResult Namespace::setTree(exprs::Ast &t) {
|
|||
std::shared_ptr<Namespace>
|
||||
makeNamespace(SereneContext &ctx, llvm::StringRef name,
|
||||
llvm::Optional<llvm::StringRef> filename, bool setCurrent) {
|
||||
auto nsPtr = std::make_shared<Namespace>(name, filename);
|
||||
auto nsPtr = std::make_shared<Namespace>(ctx, name, filename);
|
||||
ctx.insertNS(nsPtr);
|
||||
if (setCurrent) {
|
||||
assert(ctx.setCurrentNS(nsPtr->name) && "Couldn't set the current NS");
|
||||
if (!ctx.setCurrentNS(nsPtr->name)) {
|
||||
throw std::runtime_error("Couldn't set the current NS");
|
||||
}
|
||||
}
|
||||
return nsPtr;
|
||||
};
|
||||
|
||||
uint Namespace::nextFnCounter() { return fn_counter++; };
|
||||
|
||||
mlir::OpBuilder &Namespace::getBuilder() { return this->builder; };
|
||||
mlir::ModuleOp &Namespace::getModule() { return this->module; };
|
||||
SereneContext &Namespace::getContext() { return this->ctx; };
|
||||
|
||||
mlir::ModuleOp &Namespace::generate() {
|
||||
for (auto &x : getTree()) {
|
||||
x->generateIR(*this);
|
||||
}
|
||||
|
||||
return module;
|
||||
}
|
||||
|
||||
mlir::LogicalResult Namespace::runPasses() { return ctx.pm.run(module); };
|
||||
|
||||
void Namespace::dumpSLIR() {
|
||||
mlir::ModuleOp &m = generate();
|
||||
m->dump();
|
||||
};
|
||||
|
||||
void Namespace::dumpToIR() {
|
||||
// We don't want this module just yet
|
||||
|
||||
mlir::ModuleOp &m = generate();
|
||||
if (mlir::failed(runPasses())) {
|
||||
// TODO: throw a proper errer
|
||||
return;
|
||||
}
|
||||
|
||||
m->dump();
|
||||
};
|
||||
|
||||
Namespace::~Namespace() {}
|
||||
|
||||
} // namespace serene
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
/**
|
||||
* Serene programming language.
|
||||
*
|
||||
* Copyright (c) 2020 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/sir/dialect.hpp"
|
||||
|
||||
#include "mlir/IR/Builders.h"
|
||||
#include "mlir/IR/BuiltinTypes.h"
|
||||
#include "mlir/IR/OpImplementation.h"
|
||||
|
||||
namespace serene {
|
||||
namespace sir {
|
||||
|
||||
/// Dialect initialization, the instance will be owned by the context. This is
|
||||
/// the point of registration of types and operations for the dialect.
|
||||
void SereneDialect::initialize() {
|
||||
addOperations<
|
||||
#define GET_OP_LIST
|
||||
#include "serene/sir/ops.cpp.inc"
|
||||
>();
|
||||
}
|
||||
|
||||
} // namespace sir
|
||||
} // namespace serene
|
||||
|
||||
#define GET_OP_CLASSES
|
||||
#include "serene/sir/ops.cpp.inc"
|
|
@ -1,200 +0,0 @@
|
|||
/**
|
||||
* Serene programming language.
|
||||
*
|
||||
* Copyright (c) 2020 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/sir/generator.hpp"
|
||||
#include "mlir/IR/Builders.h"
|
||||
#include "mlir/IR/BuiltinOps.h"
|
||||
#include "mlir/IR/Identifier.h"
|
||||
#include "mlir/IR/MLIRContext.h"
|
||||
#include "mlir/IR/Value.h"
|
||||
#include "serene/expr.hpp"
|
||||
#include "serene/sir/dialect.hpp"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/ScopedHashTable.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
namespace serene {
|
||||
namespace sir {
|
||||
|
||||
mlir::ModuleOp Generator::generate() {
|
||||
// for (auto x : ns->Tree()) {
|
||||
// generate(x.get());
|
||||
// }
|
||||
|
||||
return module;
|
||||
};
|
||||
|
||||
mlir::Operation *Generator::generate(AExpr *x) {
|
||||
// switch (x->getType()) {
|
||||
// case SereneType::Number: {
|
||||
// return generate(llvm::cast<Number>(x));
|
||||
// }
|
||||
|
||||
// case SereneType::List: {
|
||||
// generate(llvm::cast<List>(x));
|
||||
// return nullptr;
|
||||
// }
|
||||
|
||||
// default: {
|
||||
return builder.create<ValueOp>(builder.getUnknownLoc(), (uint64_t)3);
|
||||
// }
|
||||
// }
|
||||
};
|
||||
|
||||
mlir::Value Generator::generate(List *l) {
|
||||
// auto first = l->at(0);
|
||||
|
||||
// if (!first) {
|
||||
// // Empty list.
|
||||
// // TODO: Return Nil or empty list.
|
||||
|
||||
// // Just for now.
|
||||
// return builder.create<ValueOp>(builder.getUnknownLoc(), (uint64_t)0);
|
||||
// }
|
||||
|
||||
// if (first->get()->getType() == SereneType::Symbol) {
|
||||
// auto fnNameSymbol = llvm::dyn_cast<Symbol>(first->get());
|
||||
|
||||
// if (fnNameSymbol->getName() == "fn") {
|
||||
// if (l->count() <= 3) {
|
||||
// module.emitError("'fn' form needs exactly 2 arguments.");
|
||||
// }
|
||||
|
||||
// auto args = llvm::dyn_cast<List>(l->at(1).getValue().get());
|
||||
// auto body = llvm::dyn_cast<List>(l->from(2).get());
|
||||
|
||||
// if (!args) {
|
||||
// module.emitError("The first element of 'def' has to be a symbol.");
|
||||
// }
|
||||
|
||||
// // Create a new anonymous function and push it to the anonymous
|
||||
// functions
|
||||
// // map, later on we
|
||||
// auto loc(fnNameSymbol->location->start);
|
||||
// auto anonymousName = fmt::format("__fn_{}__", anonymousFnCounter);
|
||||
// anonymousFnCounter++;
|
||||
|
||||
// auto fn = generateFn(loc, anonymousName, args, body);
|
||||
// mlir::Identifier fnid = builder.getIdentifier(anonymousName);
|
||||
// anonymousFunctions.insert({fnid, fn});
|
||||
// return builder.create<FnIdOp>(builder.getUnknownLoc(), fnid.str());
|
||||
// }
|
||||
// }
|
||||
// // auto rest = l->from(1);
|
||||
// // auto loc = toMLIRLocation(&first->get()->location->start);
|
||||
// // for (auto x : *rest) {
|
||||
// // generate(x.get());
|
||||
// // }
|
||||
|
||||
return builder.create<ValueOp>(builder.getUnknownLoc(), (uint64_t)100);
|
||||
};
|
||||
|
||||
// mlir::FuncOp Generator::generateFn(serene::reader::Location loc,
|
||||
// std::string name, List *args, List *body)
|
||||
// {
|
||||
|
||||
// auto location = toMLIRLocation(&loc);
|
||||
// llvm::SmallVector<mlir::Type, 4> arg_types(args->count(),
|
||||
// builder.getI64Type());
|
||||
// auto func_type = builder.getFunctionType(arg_types, builder.getI64Type());
|
||||
// auto proto = mlir::FuncOp::create(location, name, func_type);
|
||||
// mlir::FuncOp fn(proto);
|
||||
|
||||
// if (!fn) {
|
||||
// module.emitError("Can not create the function.");
|
||||
// }
|
||||
|
||||
// auto &entryBlock = *fn.addEntryBlock();
|
||||
// llvm::ScopedHashTableScope<llvm::StringRef, mlir::Value>
|
||||
// scope(symbolTable);
|
||||
|
||||
// // Declare all the function arguments in the symbol table.
|
||||
// for (const auto arg :
|
||||
// llvm::zip(args->asArrayRef(), entryBlock.getArguments())) {
|
||||
|
||||
// auto argSymbol = llvm::dyn_cast<Symbol>(std::get<0>(arg).get());
|
||||
// if (!argSymbol) {
|
||||
// module.emitError("Function parameters must be symbols");
|
||||
// }
|
||||
// if (symbolTable.count(argSymbol->getName())) {
|
||||
// return nullptr;
|
||||
// }
|
||||
// symbolTable.insert(argSymbol->getName(), std::get<1>(arg));
|
||||
// }
|
||||
|
||||
// // Set the insertion point in the builder to the beginning of the function
|
||||
// // body, it will be used throughout the codegen to create operations in
|
||||
// this
|
||||
// // function.
|
||||
// builder.setInsertionPointToStart(&entryBlock);
|
||||
|
||||
// // Emit the body of the function.
|
||||
// if (!generate(body)) {
|
||||
// fn.erase();
|
||||
// return nullptr;
|
||||
// }
|
||||
|
||||
// // // Implicitly return void if no return statement was emitted.
|
||||
// // // FIXME: we may fix the parser instead to always return the last
|
||||
// // expression
|
||||
// // // (this would possibly help the REPL case later)
|
||||
// // ReturnOp returnOp;
|
||||
|
||||
// // if (!entryBlock.empty())
|
||||
// // returnOp = dyn_cast<ReturnOp>(entryBlock.back());
|
||||
// // if (!returnOp) {
|
||||
// // builder.create<ReturnOp>(loc(funcAST.getProto()->loc()));
|
||||
// // } else if (returnOp.hasOperand()) {
|
||||
// // // Otherwise, if this return operation has an operand then add a
|
||||
// result
|
||||
// // to
|
||||
// // // the function.
|
||||
// // function.setType(builder.getFunctionType(function.getType().getInputs(),
|
||||
// // getType(VarType{})));
|
||||
// // }
|
||||
|
||||
// return fn;
|
||||
// }
|
||||
|
||||
mlir::Operation *Generator::generate(Number *x) {
|
||||
return builder.create<ValueOp>(builder.getUnknownLoc(), x->toI64());
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert a Serene location to MLIR FileLineLoc Location
|
||||
*/
|
||||
::mlir::Location Generator::toMLIRLocation(serene::reader::Location *loc) {
|
||||
auto file = ns->filename;
|
||||
std::string filename{file.getValueOr("REPL")};
|
||||
|
||||
return mlir::FileLineColLoc::get(builder.getIdentifier(filename), loc->line,
|
||||
loc->col);
|
||||
}
|
||||
|
||||
Generator::~Generator(){};
|
||||
} // namespace sir
|
||||
|
||||
} // namespace serene
|
|
@ -1,59 +0,0 @@
|
|||
/**
|
||||
* Serene programming language.
|
||||
*
|
||||
* Copyright (c) 2020 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/sir/sir.hpp"
|
||||
#include "mlir/IR/MLIRContext.h"
|
||||
#include "serene/exprs/expression.h"
|
||||
#include "serene/sir/dialect.hpp"
|
||||
#include "serene/sir/generator.hpp"
|
||||
#include <memory>
|
||||
|
||||
namespace serene {
|
||||
namespace sir {
|
||||
SIR::SIR() { context.getOrLoadDialect<::serene::sir::SereneDialect>(); }
|
||||
|
||||
mlir::OwningModuleRef SIR::generate(::serene::Namespace *ns) {
|
||||
auto g = std::make_unique<Generator>(context, ns);
|
||||
|
||||
return g->generate();
|
||||
};
|
||||
|
||||
SIR::~SIR() {}
|
||||
|
||||
void dumpSIR(exprs::ast &t) {
|
||||
auto ns = new ::serene::Namespace("user", llvm::None);
|
||||
|
||||
SIR s{};
|
||||
|
||||
if (failed(ns->setTree(t))) {
|
||||
llvm::errs() << "Can't set the body of the namespace";
|
||||
return;
|
||||
}
|
||||
|
||||
auto module = s.generate(ns);
|
||||
module->dump();
|
||||
};
|
||||
|
||||
} // namespace sir
|
||||
} // namespace serene
|
|
@ -1,34 +0,0 @@
|
|||
/**
|
||||
* Serene programming language.
|
||||
*
|
||||
* Copyright (c) 2020 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 "mlir/IR/Builders.h"
|
||||
#include "mlir/IR/MLIRContext.h"
|
||||
#include "mlir/IR/Value.h"
|
||||
#include "serene/sir/dialect.hpp"
|
||||
#include "serene/sir/sir.hpp"
|
||||
#include "llvm/Support/Casting.h"
|
||||
|
||||
namespace serene {
|
||||
namespace sir {} // namespace sir
|
||||
} // namespace serene
|
|
@ -22,14 +22,16 @@
|
|||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "serene/slir/generator.h"
|
||||
#include "serene/slir/generatable.h"
|
||||
#include "mlir/IR/Builders.h"
|
||||
#include "mlir/IR/BuiltinOps.h"
|
||||
#include "mlir/IR/Identifier.h"
|
||||
#include "mlir/IR/MLIRContext.h"
|
||||
#include "mlir/IR/Value.h"
|
||||
#include "serene/exprs/expression.h"
|
||||
#include "mlir/Support/LogicalResult.h"
|
||||
//#include "serene/exprs/expression.h"
|
||||
#include "serene/exprs/traits.h"
|
||||
#include "serene/namespace.h"
|
||||
#include "serene/slir/dialect.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/ScopedHashTable.h"
|
||||
|
@ -40,83 +42,82 @@
|
|||
namespace serene {
|
||||
namespace slir {
|
||||
|
||||
mlir::ModuleOp Generator::generate() {
|
||||
for (auto &x : ns->getTree()) {
|
||||
auto *num = llvm::dyn_cast<exprs::Number>(x.get());
|
||||
if (num) {
|
||||
generate(*num);
|
||||
} else {
|
||||
llvm::outs() << "else\n";
|
||||
}
|
||||
}
|
||||
|
||||
return module;
|
||||
template <typename T> mlir::ModuleOp &Generatable<T>::generate() {
|
||||
return this->Object().generate();
|
||||
};
|
||||
|
||||
mlir::Operation *Generator::generate(exprs::Expression *x) {
|
||||
// switch (x->getType()) {
|
||||
// case SereneType::Number: {
|
||||
// return generate(llvm::cast<Number>(x));
|
||||
// }
|
||||
|
||||
// case SereneType::List: {
|
||||
// generate(llvm::cast<List>(x));
|
||||
// return nullptr;
|
||||
// }
|
||||
|
||||
// default: {
|
||||
return builder.create<ValueOp>(builder.getUnknownLoc(), (uint64_t)3);
|
||||
// }
|
||||
// }
|
||||
template <typename T> mlir::LogicalResult Generatable<T>::runPasses() {
|
||||
return this->Object().runPasses();
|
||||
};
|
||||
|
||||
mlir::Value Generator::generate(exprs::List *l) {
|
||||
// auto first = l->at(0);
|
||||
|
||||
// if (!first) {
|
||||
// // Empty list.
|
||||
// // TODO: Return Nil or empty list.
|
||||
|
||||
// // Just for now.
|
||||
// return builder.create<ValueOp>(builder.getUnknownLoc(), (uint64_t)0);
|
||||
// }
|
||||
|
||||
// if (first->get()->getType() == SereneType::Symbol) {
|
||||
// auto fnNameSymbol = llvm::dyn_cast<Symbol>(first->get());
|
||||
|
||||
// if (fnNameSymbol->getName() == "fn") {
|
||||
// if (l->count() <= 3) {
|
||||
// module.emitError("'fn' form needs exactly 2 arguments.");
|
||||
// }
|
||||
|
||||
// auto args = llvm::dyn_cast<List>(l->at(1).getValue().get());
|
||||
// auto body = llvm::dyn_cast<List>(l->from(2).get());
|
||||
|
||||
// if (!args) {
|
||||
// module.emitError("The first element of 'def' has to be a symbol.");
|
||||
// }
|
||||
|
||||
// // Create a new anonymous function and push it to the anonymous
|
||||
// functions
|
||||
// // map, later on we
|
||||
// auto loc(fnNameSymbol->location->start);
|
||||
// auto anonymousName = fmt::format("__fn_{}__", anonymousFnCounter);
|
||||
// anonymousFnCounter++;
|
||||
|
||||
// auto fn = generateFn(loc, anonymousName, args, body);
|
||||
// mlir::Identifier fnid = builder.getIdentifier(anonymousName);
|
||||
// anonymousFunctions.insert({fnid, fn});
|
||||
// return builder.create<FnIdOp>(builder.getUnknownLoc(), fnid.str());
|
||||
// }
|
||||
// }
|
||||
// // auto rest = l->from(1);
|
||||
// // auto loc = toMLIRLocation(&first->get()->location->start);
|
||||
// // for (auto x : *rest) {
|
||||
// // generate(x.get());
|
||||
// // }
|
||||
return builder.create<ValueOp>(builder.getUnknownLoc(), (uint64_t)100);
|
||||
template <typename T> void Generatable<T>::dumpSLIR() {
|
||||
this->Object().dumpSLIR();
|
||||
};
|
||||
|
||||
// mlir::Operation *Generatable::generate(exprs::Expression *x) {
|
||||
// switch (x->getType()) {
|
||||
// case SereneType::Number: {
|
||||
// return generate(llvm::cast<Number>(x));
|
||||
// }
|
||||
|
||||
// case SereneType::List: {
|
||||
// generate(llvm::cast<List>(x));
|
||||
// return nullptr;
|
||||
// }
|
||||
|
||||
// default: {
|
||||
// return builder.create<ValueOp>(builder.getUnknownLoc(), (uint64_t)3);
|
||||
// }
|
||||
// }
|
||||
//};
|
||||
|
||||
// mlir::Value Generator::generate(exprs::List *l) {
|
||||
// auto first = l->at(0);
|
||||
|
||||
// if (!first) {
|
||||
// // Empty list.
|
||||
// // TODO: Return Nil or empty list.
|
||||
|
||||
// // Just for now.
|
||||
// return builder.create<ValueOp>(builder.getUnknownLoc(), (uint64_t)0);
|
||||
// }
|
||||
|
||||
// if (first->get()->getType() == SereneType::Symbol) {
|
||||
// auto fnNameSymbol = llvm::dyn_cast<Symbol>(first->get());
|
||||
|
||||
// if (fnNameSymbol->getName() == "fn") {
|
||||
// if (l->count() <= 3) {
|
||||
// module.emitError("'fn' form needs exactly 2 arguments.");
|
||||
// }
|
||||
|
||||
// auto args = llvm::dyn_cast<List>(l->at(1).getValue().get());
|
||||
// auto body = llvm::dyn_cast<List>(l->from(2).get());
|
||||
|
||||
// if (!args) {
|
||||
// module.emitError("The first element of 'def' has to be a symbol.");
|
||||
// }
|
||||
|
||||
// // Create a new anonymous function and push it to the anonymous
|
||||
// functions
|
||||
// // map, later on we
|
||||
// auto loc(fnNameSymbol->location->start);
|
||||
// auto anonymousName = fmt::format("__fn_{}__", anonymousFnCounter);
|
||||
// anonymousFnCounter++;
|
||||
|
||||
// auto fn = generateFn(loc, anonymousName, args, body);
|
||||
// mlir::Identifier fnid = builder.getIdentifier(anonymousName);
|
||||
// anonymousFunctions.insert({fnid, fn});
|
||||
// return builder.create<FnIdOp>(builder.getUnknownLoc(), fnid.str());
|
||||
// }
|
||||
// }
|
||||
// // auto rest = l->from(1);
|
||||
// // auto loc = toMLIRLocation(&first->get()->location->start);
|
||||
// // for (auto x : *rest) {
|
||||
// // generate(x.get());
|
||||
// // }
|
||||
// return builder.create<ValueOp>(builder.getUnknownLoc(), (uint64_t)100);
|
||||
//};
|
||||
|
||||
// mlir::FuncOp Generator::generateFn(serene::reader::Location loc,
|
||||
// std::string name, List *args, List *body)
|
||||
// {
|
||||
|
@ -183,28 +184,6 @@ mlir::Value Generator::generate(exprs::List *l) {
|
|||
|
||||
// return fn;
|
||||
// }
|
||||
|
||||
void Generator::generate(exprs::Number &x) {
|
||||
auto op =
|
||||
builder.create<ValueOp>(toMLIRLocation(x.location.start), x.toI64());
|
||||
|
||||
if (op) {
|
||||
module.push_back(op);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert a Serene location to MLIR FileLineLoc Location
|
||||
*/
|
||||
::mlir::Location Generator::toMLIRLocation(serene::reader::Location &loc) {
|
||||
auto file = this->ns->filename;
|
||||
std::string filename{file.getValueOr("REPL")};
|
||||
|
||||
return mlir::FileLineColLoc::get(builder.getIdentifier(filename), loc.line,
|
||||
loc.col);
|
||||
}
|
||||
|
||||
Generator::~Generator(){};
|
||||
} // namespace slir
|
||||
|
||||
} // namespace serene
|
|
@ -1,66 +0,0 @@
|
|||
/* -*- C++ -*-
|
||||
* 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/slir.h"
|
||||
#include "mlir/IR/MLIRContext.h"
|
||||
#include "serene/exprs/expression.h"
|
||||
#include "serene/namespace.h"
|
||||
#include "serene/slir/dialect.h"
|
||||
#include "serene/slir/generator.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <memory>
|
||||
|
||||
namespace serene {
|
||||
namespace slir {
|
||||
|
||||
SLIR::SLIR(serene::SereneContext &ctx) : context(ctx) {
|
||||
context.mlirContext.getOrLoadDialect<serene::slir::SereneDialect>();
|
||||
}
|
||||
|
||||
mlir::OwningModuleRef SLIR::generate(llvm::StringRef ns_name) {
|
||||
auto g = std::make_unique<Generator>(context, ns_name);
|
||||
|
||||
return g->generate();
|
||||
};
|
||||
|
||||
SLIR::~SLIR() {}
|
||||
|
||||
void dumpSLIR(serene::SereneContext &ctx, llvm::StringRef ns_name) {
|
||||
SLIR s(ctx);
|
||||
auto ns = ctx.getNS(ns_name);
|
||||
|
||||
assert(ns && "No such a namespace to dump!");
|
||||
|
||||
auto module = s.generate(ns_name);
|
||||
|
||||
if (mlir::failed(ctx.pm.run(*module))) {
|
||||
// TODO: throw a proper errer
|
||||
llvm::outs() << "Pass manager has faild!\n";
|
||||
}
|
||||
|
||||
module->dump();
|
||||
};
|
||||
|
||||
} // namespace slir
|
||||
} // namespace serene
|
|
@ -1,7 +1,7 @@
|
|||
/**
|
||||
/* -*- C++ -*-
|
||||
* Serene programming language.
|
||||
*
|
||||
* Copyright (c) 2020 Sameer Rahmani <lxsameer@gnu.org>
|
||||
* 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
|
||||
|
@ -22,22 +22,19 @@
|
|||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef DIALECT_H_
|
||||
#define DIALECT_H_
|
||||
|
||||
#include "mlir/IR/BuiltinOps.h"
|
||||
#include "mlir/IR/Dialect.h"
|
||||
#include "mlir/Interfaces/SideEffectInterfaces.h"
|
||||
#include "serene/namespace.h"
|
||||
#include "serene/reader/location.h"
|
||||
|
||||
// Include the auto-generated header file containing the declaration of the
|
||||
// serene's dialect.
|
||||
#include "serene/sir/dialect.hpp.inc"
|
||||
namespace serene::slir {
|
||||
::mlir::Location toMLIRLocation(serene::Namespace &ns,
|
||||
serene::reader::Location &loc) {
|
||||
mlir::OpBuilder &builder = ns.getBuilder();
|
||||
auto file = ns.filename;
|
||||
std::string filename{file.getValueOr("REPL")};
|
||||
|
||||
// Include the auto-generated header file containing the declarations of the
|
||||
// serene's operations.
|
||||
// for more on GET_OP_CLASSES: https://mlir.llvm.org/docs/OpDefinitions/
|
||||
#define GET_OP_CLASSES
|
||||
return mlir::FileLineColLoc::get(builder.getIdentifier(filename), loc.line,
|
||||
loc.col);
|
||||
}
|
||||
|
||||
#include "serene/sir/ops.hpp.inc"
|
||||
|
||||
#endif // DIALECT_H_
|
||||
} // namespace serene::slir
|
Loading…
Reference in New Issue