Add Ptr type and constrain and break types/ops out of dialect file
This commit is contained in:
parent
57f71ec4f2
commit
3f025a1a85
|
@ -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 ®istry);
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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 ®istry) {
|
||||
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"
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue