| //===- 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>(); |
| } |