aboutsummaryrefslogtreecommitdiff
path: root/mlir/lib/Dialect/LLVMIR/IR/LLVMDialectBytecode.cpp
blob: 41d1f80580cf7241fd2b7a47c5af4aea174df3f2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
//===- 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>();
}