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