blob: 41d1f80580cf7241fd2b7a47c5af4aea174df3f2 [file] [log] [blame] [edit]
//===- LLVMDialectBytecode.cpp - LLVM Bytecode Implementation -------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "LLVMDialectBytecode.h"
#include "mlir/Bytecode/BytecodeImplementation.h"
#include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
#include "mlir/Dialect/LLVMIR/LLVMTypes.h"
#include "mlir/IR/Diagnostics.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/TypeSwitch.h"
#include <type_traits>
using namespace mlir;
using namespace mlir::LLVM;
namespace {
// Provide some forward declarations of the functions that will be generated by
// the include below.
static void write(DIExpressionElemAttr attribute,
DialectBytecodeWriter &writer);
static LogicalResult writeAttribute(Attribute attribute,
DialectBytecodeWriter &writer);
//===--------------------------------------------------------------------===//
// Optional ArrayRefs
//
// Note that both the writer and reader functions consider attributes to be
// optional. This is because the attribute may be present or empty.
//===--------------------------------------------------------------------===//
template <class EntryTy>
static void writeOptionalArrayRef(DialectBytecodeWriter &writer,
ArrayRef<EntryTy> storage) {
if (storage.empty()) {
writer.writeOwnedBool(false);
return;
}
writer.writeOwnedBool(true);
writer.writeList(storage, [&](EntryTy val) {
if constexpr (std::is_base_of_v<Attribute, EntryTy>) {
(void)writer.writeOptionalAttribute(val);
} else if constexpr (std::is_integral_v<EntryTy>) {
(void)writer.writeVarInt(val);
} else {
static_assert(true, "EntryTy not supported");
}
});
}
template <class EntryTy>
static LogicalResult readOptionalArrayRef(DialectBytecodeReader &reader,
SmallVectorImpl<EntryTy> &storage) {
bool isPresent = false;
if (failed(reader.readBool(isPresent)))
return failure();
// Nothing to do here, the array is empty.
if (!isPresent)
return success();
auto readEntry = [&]() -> FailureOr<EntryTy> {
EntryTy temp;
if constexpr (std::is_base_of_v<Attribute, EntryTy>) {
if (succeeded(reader.readOptionalAttribute(temp)))
return temp;
} else if constexpr (std::is_integral_v<EntryTy>) {
if (succeeded(reader.readVarInt(temp)))
return temp;
} else {
static_assert(true, "EntryTy not supported");
}
return failure();
};
return reader.readList(storage, readEntry);
}
//===--------------------------------------------------------------------===//
// Optional integral types
//===--------------------------------------------------------------------===//
template <class EntryTy>
static void writeOptionalInt(DialectBytecodeWriter &writer,
std::optional<EntryTy> storage) {
static_assert(std::is_integral_v<EntryTy>,
"EntryTy must be an integral type");
EntryTy val = storage.value_or(0);
writer.writeVarIntWithFlag(val, storage.has_value());
}
template <class EntryTy>
static LogicalResult readOptionalInt(DialectBytecodeReader &reader,
std::optional<EntryTy> &storage) {
static_assert(std::is_integral_v<EntryTy>,
"EntryTy must be an integral type");
uint64_t result = 0;
bool flag = false;
if (failed(reader.readVarIntWithFlag(result, flag)))
return failure();
if (flag)
storage = static_cast<EntryTy>(result);
else
storage = std::nullopt;
return success();
}
//===--------------------------------------------------------------------===//
// Tablegen generated bytecode functions
//===--------------------------------------------------------------------===//
#include "mlir/Dialect/LLVMIR/LLVMDialectBytecode.cpp.inc"
//===--------------------------------------------------------------------===//
// LLVMDialectBytecodeInterface
//===--------------------------------------------------------------------===//
/// This class implements the bytecode interface for the LLVM dialect.
struct LLVMDialectBytecodeInterface : public BytecodeDialectInterface {
LLVMDialectBytecodeInterface(Dialect *dialect)
: BytecodeDialectInterface(dialect) {}
// Attributes
Attribute readAttribute(DialectBytecodeReader &reader) const override {
return ::readAttribute(getContext(), reader);
}
LogicalResult writeAttribute(Attribute attr,
DialectBytecodeWriter &writer) const override {
return ::writeAttribute(attr, writer);
}
// Types
Type readType(DialectBytecodeReader &reader) const override {
return ::readType(getContext(), reader);
}
LogicalResult writeType(Type type,
DialectBytecodeWriter &writer) const override {
return ::writeType(type, writer);
}
};
} // namespace
void LLVM::detail::addBytecodeInterface(LLVMDialect *dialect) {
dialect->addInterfaces<LLVMDialectBytecodeInterface>();
}