Add Ptr type and constrain and break types/ops out of dialect file

This commit is contained in:
Sameer Rahmani 2022-06-05 00:02:25 +01:00
parent 57f71ec4f2
commit 3f025a1a85
8 changed files with 217 additions and 110 deletions

View File

@ -36,13 +36,7 @@
// Include the auto-generated header file containing the declaration of the
// serene's dialect.
#include "serene/slir/dialect.h.inc"
#define GET_TYPEDEF_CLASSES
#include "serene/slir/types.h.inc"
// 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
#include "serene/slir/ops.h.inc"
#include "serene/slir/types.h"
namespace serene::slir {
SERENE_EXPORT void registerTo(mlir::DialectRegistry &registry);

View File

@ -0,0 +1,40 @@
/* -*- C++ -*-
* 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_DIALECT_OPS_H
#define SERENE_DIALECT_OPS_H
#include "serene/slir/types.h"
#include <llvm/ADT/TypeSwitch.h>
#include <mlir/Dialect/Arithmetic/IR/Arithmetic.h>
#include <mlir/Dialect/Func/IR/FuncOps.h>
#include <mlir/Dialect/LLVMIR/LLVMDialect.h>
#include <mlir/IR/BuiltinOps.h>
#include <mlir/IR/Dialect.h>
#include <mlir/IR/DialectRegistry.h>
#include <mlir/IR/FunctionInterfaces.h>
#include <mlir/Interfaces/CallInterfaces.h>
#include <mlir/Interfaces/ControlFlowInterfaces.h>
#include <mlir/Interfaces/InferTypeOpInterface.h>
#include <mlir/Interfaces/SideEffectInterfaces.h>
#define GET_OP_CLASSES
#include "serene/slir/ops.h.inc"
#endif

View File

@ -0,0 +1,31 @@
/* -*- C++ -*-
* 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_DIALECT_TYPES_H
#define SERENE_DIALECT_TYPES_H
#include <llvm/ADT/TypeSwitch.h>
#include <mlir/IR/BuiltinOps.h>
#include <mlir/IR/BuiltinTypes.h>
#include <mlir/IR/DialectImplementation.h>
#include <mlir/IR/TypeSupport.h>
#define GET_TYPEDEF_CLASSES
#include "serene/slir/types.h.inc"
#endif

View File

@ -16,13 +16,61 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SERENE_DIALECT_TYPES
#define SERENE_DIALECT_TYPES
#ifndef SERENE_DIALECT_TYPES_TD
#define SERENE_DIALECT_TYPES_TD
include "mlir/IR/OpBase.td"
// All of the types will extend this class.
class Serene_Type<string name> : TypeDef<Serene_Dialect, name> { }
def SereneString : Serene_Type<"String"> {
def AnyPtr : Type<CPred<"$_self.isa<PtrType>()">,
"Serene pointer type", "Ptr">;
class Ptr<Type type> : Type<
And<[AnyPtr.predicate,
Or<[CPred<"$_self.cast<PtrType>().isOpaque()">,
SubstLeaves<
"$_self",
"$_self.cast<PtrType>().getPointeeType()",
type.predicate>]>]>,
"A pointer to type " # type.summary,
"PtrType">,
// We need Ptr to be buildable coz we need to be able to infer
// the type out of it when we use Ptr<T> as the result type
// of an operation
SameBuildabilityAs<type, "PtrType::get(" # type # "::get($_builder.getContext()))"> {
Type pointeeType = type;
}
def PtrType : Serene_Type<"Ptr"> {
let mnemonic = "ptr";
let summary = "A pointer to a value of type T.";
let description = [{
A pointer to a value of type T. For example
%0 = serene.address-of %1 : (!serene.symbol) -> !ptr<serene.symbol>
}];
let parameters = (ins "mlir::Type":$pointeeType, DefaultValuedParameter<"unsigned", "0">:$addressSpace);
let genAccessors = 1;
let assemblyFormat = "`<` qualified($pointeeType) `>`";
let extraClassDeclaration = [{
/// Gets or creates an instance of pointer type pointing to an
/// object of `pointee` type in the given address space. The pointer type is
/// created in the same context as `pointee`. If the pointee is not provided,
/// creates an opaque pointer in the given context and address space.
static PtrType get(mlir::MLIRContext *context, unsigned addressSpace = 0);
static PtrType get(mlir::Type pointee, unsigned addressSpace = 0);
bool isOpaque() const;
}];
}
def StringType : Serene_Type<"String"> {
let mnemonic = "string";
let summary = "A simple string type";
@ -35,7 +83,7 @@ def SereneString : Serene_Type<"String"> {
}
def SereneSymbol : Serene_Type<"Symbol"> {
def SymbolType : Serene_Type<"Symbol"> {
let mnemonic = "symbol";
let summary = "A Lisp symbol type";
@ -46,7 +94,7 @@ def SereneSymbol : Serene_Type<"Symbol"> {
// let parameters = (ins "std::string":$ns, "std::string":$name);
}
def SereneFn : Serene_Type<"Fn"> {
def FnType : Serene_Type<"Fn"> {
let mnemonic = "fn";
let summary = "Function type";
@ -61,4 +109,11 @@ def SereneFn : Serene_Type<"Fn"> {
// let parameters = (ins "std::string":$ns, "std::string":$name);
}
#endif // SERENE_DIALECT_TYPES
def Serene_Type : AnyTypeOf<[
PtrType,
SymbolType,
StringType,
FnType
]>;
#endif // SERENE_DIALECT_TYPES_TD

View File

@ -18,9 +18,12 @@
#include "serene/context.h"
#include "serene/conventions.h"
#include "serene/diagnostics.h"
#include "serene/passes.h"
#include "serene/slir/dialect.h"
#include "serene/slir/ops.h"
#include "serene/slir/type_converter.h"
#include "serene/slir/types.h"
#include "serene/utils.h"
#include <serene/config.h>
@ -112,6 +115,12 @@ static ll::GlobalOp getOrCreateString(mlir::Location loc,
auto &gr = global.getInitializerRegion();
auto *block = builder.createBlock(&gr);
if (block == nullptr) {
module.emitError("Faild to create block of the globalOp!");
// TODO: change the return type to Expected<GlobalOp> and return
// an error here
}
builder.setInsertionPoint(block, block->begin());
mlir::Value structInstant = builder.create<ll::UndefOp>(loc, type);
@ -168,6 +177,12 @@ static ll::GlobalOp getOrCreateSymbol(mlir::Location loc,
auto &gr = global.getInitializerRegion();
auto *block = builder.createBlock(&gr);
if (block == nullptr) {
module.emitError("Faild to create block of the globalOp!");
// TODO: change the return type to Expected<GlobalOp> and return
// an error here
}
builder.setInsertionPoint(block, block->begin());
mlir::Value structInstant = builder.create<ll::UndefOp>(loc, type);
@ -216,22 +231,22 @@ mlir::LogicalResult
LowerSymbol::matchAndRewrite(serene::slir::SymbolOp op, OpAdaptor adaptor,
mlir::ConversionPatternRewriter &rewriter) const {
UNUSED(adaptor);
auto ns = op.ns();
auto name = op.name();
auto loc = op.getLoc();
auto module = op->getParentOfType<mlir::ModuleOp>();
// If there is no use for the result of this op then simply erase it
// if (!op.getResult().use_empty()) {
// rewriter.eraseOp(op);
// return mlir::success();
// }
if (op.getResult().use_empty()) {
rewriter.eraseOp(op);
return mlir::success();
}
auto global = getOrCreateSymbol(loc, rewriter, ns, name, module);
rewriter.eraseOp(op);
auto ptr = rewriter.create<ll::AddressOfOp>(loc, global);
(void)adaptor;
(void)global;
rewriter.replaceOp(op, ptr.getResult());
return mlir::success();
}
@ -277,8 +292,10 @@ LowerDefine::matchAndRewrite(serene::slir::DefineOp op, OpAdaptor adaptor,
op, op.sym_name(), constantValue, rewriter.getBoolAttr(isTopLevel),
op.sym_visibilityAttr());
// TODO: Erase the valueop if it has no other 'use' in the IR
// rewriter.eraseOp(valueop);
if (valueop->use_empty()) {
PASS_LOG("Erase op due to empty use:" << valueop);
rewriter.eraseOp(valueop);
}
return mlir::success();
}
@ -286,6 +303,7 @@ LowerDefine::matchAndRewrite(serene::slir::DefineOp op, OpAdaptor adaptor,
// If the value was a Function literal (like an anonymous function)
// rewrite to a Func.FuncOp
if (mlir::isa<slir::FnOp>(valueop)) {
// TODO: Lower to a function op
rewriter.eraseOp(op);
return mlir::success();
}
@ -308,11 +326,7 @@ LowerDefine::matchAndRewrite(serene::slir::DefineOp op, OpAdaptor adaptor,
{
mlir::PatternRewriter::InsertionGuard insertGuard(rewriter);
auto moduleOp = op->getParentOfType<mlir::ModuleOp>();
auto &topLevelRegion = moduleOp.getBodyRegion();
auto &moduleBlock = topLevelRegion.getBlocks();
rewriter.setInsertionPointToStart(&moduleBlock.front());
rewriter.setInsertionPointToStart(moduleOp.getBody());
auto globalOp = rewriter.create<ll::GlobalOp>(loc, llvmType,
/*isConstant=*/false,
@ -321,8 +335,7 @@ LowerDefine::matchAndRewrite(serene::slir::DefineOp op, OpAdaptor adaptor,
auto *block = rewriter.createBlock(&gr);
if (block == nullptr) {
// TODO: use diagnastics
llvm::errs() << "Faild to create block of the globalOp!";
op.emitError("Faild to create block of the globalOp!");
return mlir::failure();
}

View File

@ -15,12 +15,14 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "serene/slir/dialect.h"
#include "serene/slir/dialect.cpp.inc"
#include "serene/slir/ops.h"
#include "serene/slir/types.h"
#include <mlir/IR/Builders.h>
#include <mlir/IR/BuiltinTypes.h>
#include <mlir/IR/Dialect.h>
#include <mlir/IR/DialectImplementation.h>
#include <mlir/IR/MLIRContext.h>
@ -31,95 +33,16 @@ namespace slir {
/// 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() {
registerType();
addOperations<
#define GET_OP_LIST
#include "serene/slir/ops.cpp.inc"
>();
addTypes<
#define GET_TYPEDEF_LIST
#include "serene/slir/types.cpp.inc"
>();
}
// static SymbolType parseSymbolType(mlir::MLIRContext &ctx,
// mlir::AsmParser &parser) {
// llvm::SMLoc loc = parser.getCurrentLocation();
// if (parser.parseLess()) {
// return SymbolType();
// }
// std::string fqsym;
// if(parser.parseString(&fqsym)) {
// }
// };
// /// Parses a type appearing inside another LLVM dialect-compatible type. This
// /// will try to parse any type in full form (including types with the `!llvm`
// /// prefix), and on failure fall back to parsing the short-hand version of
// the
// /// LLVM dialect types without the `!llvm` prefix.
// static mlir::Type dispatchParse(mlir::AsmParser &parser, bool allowAny =
// true) {
// llvm::SMLoc keyLoc = parser.getCurrentLocation();
// // Try parsing any MLIR type.
// mlir::Type type;
// mlir::OptionalParseResult result = parser.parseOptionalType(type);
// if (result.hasValue()) {
// if (failed(result.getValue())) {
// return nullptr;
// }
// if (!allowAny) {
// parser.emitError(keyLoc) << "unexpected type, expected keyword";
// return nullptr;
// }
// return type;
// }
// // If no type found, fallback to the shorthand form.
// llvm::StringRef key;
// if (failed(parser.parseKeyword(&key))) {
// return mlir::Type();
// }
// mlir::MLIRContext *ctx = parser.getContext();
// return mlir::StringSwitch<mlir::function_ref<mlir::Type()>>(key)
// .Case("symbol", [&] { return parseSymbolType(ctx, parser); })
// .Default([&] {
// parser.emitError(keyLoc) << "unknown LLVM type: " << key;
// return mlir::Type();
// })();
// }
// //.Case("struct", [&] { return parseStructType(parser); })
// /// Parse an instance of a type registered to the dialect.
// mlir::Type SereneDialect::parseType(mlir::DialectAsmParser &parser) const {
// llvm::SMLoc loc = parser.getCurrentLocation();
// mlir::Type type = dispatchParse(parser, /*allowAny=*/false);
// if (!type) {
// return type;
// }
// if (!isCompatibleOuterType(type)) {
// parser.emitError(loc) << "unexpected type, expected keyword";
// return nullptr;
// }
// return type;
// };
// // /// Print an instance of a type registered to the dialect.
// void SereneDialect::printType(
// mlir::Type type, mlir::DialectAsmPrinter &printer) const override{};
void registerTo(mlir::DialectRegistry &registry) {
registry.insert<serene::slir::SereneDialect>();
};
} // namespace slir
} // namespace serene
#define GET_TYPEDEF_CLASSES
#include "serene/slir/types.cpp.inc"
#define GET_OP_CLASSES
#include "serene/slir/ops.cpp.inc"

View File

@ -16,7 +16,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "serene/slir/ops.h"
#include "serene/slir/dialect.h"
#include "serene/slir/types.h"
#include "serene/utils.h"
#include <llvm/Support/FormatVariadic.h>
@ -25,6 +28,9 @@
#include <mlir/IR/BuiltinAttributes.h>
#include <mlir/IR/OperationSupport.h>
#define GET_OP_CLASSES
#include "serene/slir/ops.cpp.inc"
namespace serene::slir {
mlir::DataLayoutSpecInterface NsOp::getDataLayoutSpec() {

View File

@ -0,0 +1,45 @@
/* -*- C++ -*-
* 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/>.
*/
#include "serene/slir/types.h"
#include "serene/slir/dialect.h"
#define GET_TYPEDEF_CLASSES
#include "serene/slir/types.cpp.inc"
namespace serene::slir {
PtrType PtrType::get(mlir::MLIRContext *context, unsigned addressSpace) {
return Base::get(context, mlir::Type(), addressSpace);
}
PtrType PtrType::get(mlir::Type pointee, unsigned addressSpace) {
return Base::get(pointee.getContext(), pointee, addressSpace);
}
bool PtrType::isOpaque() const { return !getImpl()->pointeeType; }
void SereneDialect::registerType() {
addTypes<
#define GET_TYPEDEF_LIST
#include "serene/slir/types.cpp.inc"
>();
};
} // namespace serene::slir