xref: /llvm-project/mlir/lib/IR/BuiltinDialectBytecode.cpp (revision 01e75646a5d4977a9e441e3db1042df0beccc4bb)
1 //===- BuiltinDialectBytecode.cpp - Builtin Bytecode Implementation -------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "BuiltinDialectBytecode.h"
10 #include "AttributeDetail.h"
11 #include "mlir/Bytecode/BytecodeImplementation.h"
12 #include "mlir/IR/BuiltinAttributes.h"
13 #include "mlir/IR/BuiltinDialect.h"
14 #include "mlir/IR/BuiltinTypes.h"
15 #include "mlir/IR/Diagnostics.h"
16 #include "mlir/IR/DialectResourceBlobManager.h"
17 #include "mlir/IR/Location.h"
18 #include "mlir/Support/LLVM.h"
19 #include "llvm/ADT/TypeSwitch.h"
20 #include <cstdint>
21 
22 using namespace mlir;
23 
24 //===----------------------------------------------------------------------===//
25 // BuiltinDialectBytecodeInterface
26 //===----------------------------------------------------------------------===//
27 
28 namespace {
29 
30 //===----------------------------------------------------------------------===//
31 // Utility functions
32 
33 // TODO: Move these to separate file.
34 
35 // Returns the bitwidth if known, else return 0.
36 static unsigned getIntegerBitWidth(DialectBytecodeReader &reader, Type type) {
37   if (auto intType = dyn_cast<IntegerType>(type)) {
38     return intType.getWidth();
39   }
40   if (llvm::isa<IndexType>(type)) {
41     return IndexType::kInternalStorageBitWidth;
42   }
43   reader.emitError()
44       << "expected integer or index type for IntegerAttr, but got: " << type;
45   return 0;
46 }
47 
48 static LogicalResult readAPIntWithKnownWidth(DialectBytecodeReader &reader,
49                                              Type type, FailureOr<APInt> &val) {
50   unsigned bitWidth = getIntegerBitWidth(reader, type);
51   val = reader.readAPIntWithKnownWidth(bitWidth);
52   return val;
53 }
54 
55 static LogicalResult
56 readAPFloatWithKnownSemantics(DialectBytecodeReader &reader, Type type,
57                               FailureOr<APFloat> &val) {
58   auto ftype = dyn_cast<FloatType>(type);
59   if (!ftype)
60     return failure();
61   val = reader.readAPFloatWithKnownSemantics(ftype.getFloatSemantics());
62   return success();
63 }
64 
65 LogicalResult
66 readPotentiallySplatString(DialectBytecodeReader &reader, ShapedType type,
67                            bool isSplat,
68                            SmallVectorImpl<StringRef> &rawStringData) {
69   rawStringData.resize(isSplat ? 1 : type.getNumElements());
70   for (StringRef &value : rawStringData)
71     if (failed(reader.readString(value)))
72       return failure();
73   return success();
74 }
75 
76 static void writePotentiallySplatString(DialectBytecodeWriter &writer,
77                                         DenseStringElementsAttr attr) {
78   bool isSplat = attr.isSplat();
79   if (isSplat)
80     return writer.writeOwnedString(attr.getRawStringData().front());
81 
82   for (StringRef str : attr.getRawStringData())
83     writer.writeOwnedString(str);
84 }
85 
86 static FileLineColRange getFileLineColRange(MLIRContext *context,
87                                             StringAttr filename,
88                                             ArrayRef<uint64_t> lineCols) {
89   switch (lineCols.size()) {
90   case 0:
91     return FileLineColRange::get(filename);
92   case 1:
93     return FileLineColRange::get(filename, lineCols[0]);
94   case 2:
95     return FileLineColRange::get(filename, lineCols[0], lineCols[1]);
96   case 3:
97     return FileLineColRange::get(filename, lineCols[0], lineCols[1],
98                                  lineCols[2]);
99   case 4:
100     return FileLineColRange::get(filename, lineCols[0], lineCols[1],
101                                  lineCols[2], lineCols[3]);
102   default:
103     return {};
104   }
105 }
106 
107 static LogicalResult
108 readFileLineColRangeLocs(DialectBytecodeReader &reader,
109                          SmallVectorImpl<uint64_t> &lineCols) {
110   return reader.readList(
111       lineCols, [&reader](uint64_t &val) { return reader.readVarInt(val); });
112 }
113 
114 static void writeFileLineColRangeLocs(DialectBytecodeWriter &writer,
115                                       FileLineColRange range) {
116   if (range.getStartLine() == 0 && range.getStartColumn() == 0 &&
117       range.getEndLine() == 0 && range.getEndColumn() == 0) {
118     writer.writeVarInt(0);
119     return;
120   }
121   if (range.getStartColumn() == 0 &&
122       range.getStartLine() == range.getEndLine()) {
123     writer.writeVarInt(1);
124     writer.writeVarInt(range.getStartLine());
125     return;
126   }
127   // The single file:line:col is handled by other writer, but checked here for
128   // completeness.
129   if (range.getEndColumn() == range.getStartColumn() &&
130       range.getStartLine() == range.getEndLine()) {
131     writer.writeVarInt(2);
132     writer.writeVarInt(range.getStartLine());
133     writer.writeVarInt(range.getStartColumn());
134     return;
135   }
136   if (range.getStartLine() == range.getEndLine()) {
137     writer.writeVarInt(3);
138     writer.writeVarInt(range.getStartLine());
139     writer.writeVarInt(range.getStartColumn());
140     writer.writeVarInt(range.getEndColumn());
141     return;
142   }
143   writer.writeVarInt(4);
144   writer.writeVarInt(range.getStartLine());
145   writer.writeVarInt(range.getStartColumn());
146   writer.writeVarInt(range.getEndLine());
147   writer.writeVarInt(range.getEndColumn());
148 }
149 
150 #include "mlir/IR/BuiltinDialectBytecode.cpp.inc"
151 
152 /// This class implements the bytecode interface for the builtin dialect.
153 struct BuiltinDialectBytecodeInterface : public BytecodeDialectInterface {
154   BuiltinDialectBytecodeInterface(Dialect *dialect)
155       : BytecodeDialectInterface(dialect) {}
156 
157   //===--------------------------------------------------------------------===//
158   // Attributes
159 
160   Attribute readAttribute(DialectBytecodeReader &reader) const override {
161     return ::readAttribute(getContext(), reader);
162   }
163 
164   LogicalResult writeAttribute(Attribute attr,
165                                DialectBytecodeWriter &writer) const override {
166     return ::writeAttribute(attr, writer);
167   }
168 
169   //===--------------------------------------------------------------------===//
170   // Types
171 
172   Type readType(DialectBytecodeReader &reader) const override {
173     return ::readType(getContext(), reader);
174   }
175 
176   LogicalResult writeType(Type type,
177                           DialectBytecodeWriter &writer) const override {
178     return ::writeType(type, writer);
179   }
180 };
181 } // namespace
182 
183 void builtin_dialect_detail::addBytecodeInterface(BuiltinDialect *dialect) {
184   dialect->addInterfaces<BuiltinDialectBytecodeInterface>();
185 }
186