llvm-project/mlir/lib/IR/BuiltinDialectBytecode.cpp

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

1178 lines
39 KiB
C++
Raw Normal View History

//===- BuiltinDialectBytecode.cpp - Builtin 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 "BuiltinDialectBytecode.h"
#include "mlir/Bytecode/BytecodeImplementation.h"
#include "mlir/IR/BuiltinDialect.h"
#include "mlir/IR/BuiltinTypes.h"
#include "mlir/IR/Diagnostics.h"
#include "mlir/IR/DialectResourceBlobManager.h"
#include "llvm/ADT/TypeSwitch.h"
using namespace mlir;
//===----------------------------------------------------------------------===//
// Encoding
//===----------------------------------------------------------------------===//
namespace {
namespace builtin_encoding {
/// This enum contains marker codes used to indicate which attribute is
/// currently being decoded, and how it should be decoded. The order of these
/// codes should generally be unchanged, as any changes will inevitably break
/// compatibility with older bytecode.
enum AttributeCode {
/// ArrayAttr {
/// elements: Attribute[]
/// }
///
kArrayAttr = 0,
/// DictionaryAttr {
/// attrs: <StringAttr, Attribute>[]
/// }
kDictionaryAttr = 1,
/// StringAttr {
/// value: string
/// }
kStringAttr = 2,
/// StringAttrWithType {
/// value: string,
/// type: Type
/// }
/// A variant of StringAttr with a type.
kStringAttrWithType = 3,
/// FlatSymbolRefAttr {
/// rootReference: StringAttr
/// }
/// A variant of SymbolRefAttr with no leaf references.
kFlatSymbolRefAttr = 4,
/// SymbolRefAttr {
/// rootReference: StringAttr,
/// leafReferences: FlatSymbolRefAttr[]
/// }
kSymbolRefAttr = 5,
/// TypeAttr {
/// value: Type
/// }
kTypeAttr = 6,
/// UnitAttr {
/// }
kUnitAttr = 7,
/// IntegerAttr {
/// type: Type
/// value: APInt,
/// }
kIntegerAttr = 8,
/// FloatAttr {
/// type: FloatType
/// value: APFloat
/// }
kFloatAttr = 9,
/// CallSiteLoc {
/// callee: LocationAttr,
/// caller: LocationAttr
/// }
kCallSiteLoc = 10,
/// FileLineColLoc {
/// file: StringAttr,
/// line: varint,
/// column: varint
/// }
kFileLineColLoc = 11,
/// FusedLoc {
/// locations: LocationAttr[]
/// }
kFusedLoc = 12,
/// FusedLocWithMetadata {
/// locations: LocationAttr[],
/// metadata: Attribute
/// }
/// A variant of FusedLoc with metadata.
kFusedLocWithMetadata = 13,
/// NameLoc {
/// name: StringAttr,
/// childLoc: LocationAttr
/// }
kNameLoc = 14,
/// UnknownLoc {
/// }
kUnknownLoc = 15,
/// DenseResourceElementsAttr {
/// type: Type,
/// handle: ResourceHandle
/// }
kDenseResourceElementsAttr = 16,
/// DenseArrayAttr {
/// type: RankedTensorType,
/// data: blob
/// }
kDenseArrayAttr = 17,
/// DenseIntOrFPElementsAttr {
/// type: ShapedType,
/// data: blob
/// }
kDenseIntOrFPElementsAttr = 18,
/// DenseStringElementsAttr {
/// type: ShapedType,
/// isSplat: varint,
/// data: string[]
/// }
kDenseStringElementsAttr = 19,
/// SparseElementsAttr {
/// type: ShapedType,
/// indices: DenseIntElementsAttr,
/// values: DenseElementsAttr
/// }
kSparseElementsAttr = 20,
};
/// This enum contains marker codes used to indicate which type is currently
/// being decoded, and how it should be decoded. The order of these codes should
/// generally be unchanged, as any changes will inevitably break compatibility
/// with older bytecode.
enum TypeCode {
/// IntegerType {
/// widthAndSignedness: varint // (width << 2) | (signedness)
/// }
///
kIntegerType = 0,
/// IndexType {
/// }
///
kIndexType = 1,
/// FunctionType {
/// inputs: Type[],
/// results: Type[]
/// }
///
kFunctionType = 2,
/// BFloat16Type {
/// }
///
kBFloat16Type = 3,
/// Float16Type {
/// }
///
kFloat16Type = 4,
/// Float32Type {
/// }
///
kFloat32Type = 5,
/// Float64Type {
/// }
///
kFloat64Type = 6,
/// Float80Type {
/// }
///
kFloat80Type = 7,
/// Float128Type {
/// }
///
kFloat128Type = 8,
/// ComplexType {
/// elementType: Type
/// }
///
kComplexType = 9,
/// MemRefType {
/// shape: svarint[],
/// elementType: Type,
/// layout: Attribute
/// }
///
kMemRefType = 10,
/// MemRefTypeWithMemSpace {
/// memorySpace: Attribute,
/// shape: svarint[],
/// elementType: Type,
/// layout: Attribute
/// }
/// Variant of MemRefType with non-default memory space.
kMemRefTypeWithMemSpace = 11,
/// NoneType {
/// }
///
kNoneType = 12,
/// RankedTensorType {
/// shape: svarint[],
/// elementType: Type,
/// }
///
kRankedTensorType = 13,
/// RankedTensorTypeWithEncoding {
/// encoding: Attribute,
/// shape: svarint[],
/// elementType: Type
/// }
/// Variant of RankedTensorType with an encoding.
kRankedTensorTypeWithEncoding = 14,
/// TupleType {
/// elementTypes: Type[]
/// }
kTupleType = 15,
/// UnrankedMemRefType {
/// shape: svarint[]
/// }
///
kUnrankedMemRefType = 16,
/// UnrankedMemRefTypeWithMemSpace {
/// memorySpace: Attribute,
/// shape: svarint[]
/// }
/// Variant of UnrankedMemRefType with non-default memory space.
kUnrankedMemRefTypeWithMemSpace = 17,
/// UnrankedTensorType {
/// elementType: Type
/// }
///
kUnrankedTensorType = 18,
/// VectorType {
/// shape: svarint[],
/// elementType: Type
/// }
///
kVectorType = 19,
/// VectorTypeWithScalableDims {
/// numScalableDims: varint,
/// shape: svarint[],
/// elementType: Type
/// }
/// Variant of VectorType with scalable dimensions.
kVectorTypeWithScalableDims = 20,
};
} // namespace builtin_encoding
} // namespace
//===----------------------------------------------------------------------===//
// BuiltinDialectBytecodeInterface
//===----------------------------------------------------------------------===//
namespace {
/// This class implements the bytecode interface for the builtin dialect.
struct BuiltinDialectBytecodeInterface : public BytecodeDialectInterface {
BuiltinDialectBytecodeInterface(Dialect *dialect)
: BytecodeDialectInterface(dialect) {}
//===--------------------------------------------------------------------===//
// Attributes
Attribute readAttribute(DialectBytecodeReader &reader) const override;
ArrayAttr readArrayAttr(DialectBytecodeReader &reader) const;
DenseArrayAttr readDenseArrayAttr(DialectBytecodeReader &reader) const;
DenseElementsAttr
readDenseIntOrFPElementsAttr(DialectBytecodeReader &reader) const;
DenseStringElementsAttr
readDenseStringElementsAttr(DialectBytecodeReader &reader) const;
DenseResourceElementsAttr
readDenseResourceElementsAttr(DialectBytecodeReader &reader) const;
DictionaryAttr readDictionaryAttr(DialectBytecodeReader &reader) const;
FloatAttr readFloatAttr(DialectBytecodeReader &reader) const;
IntegerAttr readIntegerAttr(DialectBytecodeReader &reader) const;
SparseElementsAttr
readSparseElementsAttr(DialectBytecodeReader &reader) const;
StringAttr readStringAttr(DialectBytecodeReader &reader, bool hasType) const;
SymbolRefAttr readSymbolRefAttr(DialectBytecodeReader &reader,
bool hasNestedRefs) const;
TypeAttr readTypeAttr(DialectBytecodeReader &reader) const;
LocationAttr readCallSiteLoc(DialectBytecodeReader &reader) const;
LocationAttr readFileLineColLoc(DialectBytecodeReader &reader) const;
LocationAttr readFusedLoc(DialectBytecodeReader &reader,
bool hasMetadata) const;
LocationAttr readNameLoc(DialectBytecodeReader &reader) const;
LogicalResult writeAttribute(Attribute attr,
DialectBytecodeWriter &writer) const override;
void write(ArrayAttr attr, DialectBytecodeWriter &writer) const;
void write(DenseArrayAttr attr, DialectBytecodeWriter &writer) const;
void write(DenseIntOrFPElementsAttr attr,
DialectBytecodeWriter &writer) const;
void write(DenseStringElementsAttr attr, DialectBytecodeWriter &writer) const;
void write(DenseResourceElementsAttr attr,
DialectBytecodeWriter &writer) const;
void write(DictionaryAttr attr, DialectBytecodeWriter &writer) const;
void write(IntegerAttr attr, DialectBytecodeWriter &writer) const;
void write(FloatAttr attr, DialectBytecodeWriter &writer) const;
void write(SparseElementsAttr attr, DialectBytecodeWriter &writer) const;
void write(StringAttr attr, DialectBytecodeWriter &writer) const;
void write(SymbolRefAttr attr, DialectBytecodeWriter &writer) const;
void write(TypeAttr attr, DialectBytecodeWriter &writer) const;
void write(CallSiteLoc attr, DialectBytecodeWriter &writer) const;
void write(FileLineColLoc attr, DialectBytecodeWriter &writer) const;
void write(FusedLoc attr, DialectBytecodeWriter &writer) const;
void write(NameLoc attr, DialectBytecodeWriter &writer) const;
LogicalResult write(OpaqueLoc attr, DialectBytecodeWriter &writer) const;
//===--------------------------------------------------------------------===//
// Types
Type readType(DialectBytecodeReader &reader) const override;
ComplexType readComplexType(DialectBytecodeReader &reader) const;
IntegerType readIntegerType(DialectBytecodeReader &reader) const;
FunctionType readFunctionType(DialectBytecodeReader &reader) const;
MemRefType readMemRefType(DialectBytecodeReader &reader,
bool hasMemSpace) const;
RankedTensorType readRankedTensorType(DialectBytecodeReader &reader,
bool hasEncoding) const;
TupleType readTupleType(DialectBytecodeReader &reader) const;
UnrankedMemRefType readUnrankedMemRefType(DialectBytecodeReader &reader,
bool hasMemSpace) const;
UnrankedTensorType
readUnrankedTensorType(DialectBytecodeReader &reader) const;
VectorType readVectorType(DialectBytecodeReader &reader,
bool hasScalableDims) const;
LogicalResult writeType(Type type,
DialectBytecodeWriter &writer) const override;
void write(ComplexType type, DialectBytecodeWriter &writer) const;
void write(IntegerType type, DialectBytecodeWriter &writer) const;
void write(FunctionType type, DialectBytecodeWriter &writer) const;
void write(MemRefType type, DialectBytecodeWriter &writer) const;
void write(RankedTensorType type, DialectBytecodeWriter &writer) const;
void write(TupleType type, DialectBytecodeWriter &writer) const;
void write(UnrankedMemRefType type, DialectBytecodeWriter &writer) const;
void write(UnrankedTensorType type, DialectBytecodeWriter &writer) const;
void write(VectorType type, DialectBytecodeWriter &writer) const;
};
} // namespace
void builtin_dialect_detail::addBytecodeInterface(BuiltinDialect *dialect) {
dialect->addInterfaces<BuiltinDialectBytecodeInterface>();
}
//===----------------------------------------------------------------------===//
// Attributes
//===----------------------------------------------------------------------===//
Attribute BuiltinDialectBytecodeInterface::readAttribute(
DialectBytecodeReader &reader) const {
uint64_t code;
if (failed(reader.readVarInt(code)))
return Attribute();
switch (code) {
case builtin_encoding::kArrayAttr:
return readArrayAttr(reader);
case builtin_encoding::kDictionaryAttr:
return readDictionaryAttr(reader);
case builtin_encoding::kStringAttr:
return readStringAttr(reader, /*hasType=*/false);
case builtin_encoding::kStringAttrWithType:
return readStringAttr(reader, /*hasType=*/true);
case builtin_encoding::kFlatSymbolRefAttr:
return readSymbolRefAttr(reader, /*hasNestedRefs=*/false);
case builtin_encoding::kSymbolRefAttr:
return readSymbolRefAttr(reader, /*hasNestedRefs=*/true);
case builtin_encoding::kTypeAttr:
return readTypeAttr(reader);
case builtin_encoding::kUnitAttr:
return UnitAttr::get(getContext());
case builtin_encoding::kIntegerAttr:
return readIntegerAttr(reader);
case builtin_encoding::kFloatAttr:
return readFloatAttr(reader);
case builtin_encoding::kCallSiteLoc:
return readCallSiteLoc(reader);
case builtin_encoding::kFileLineColLoc:
return readFileLineColLoc(reader);
case builtin_encoding::kFusedLoc:
return readFusedLoc(reader, /*hasMetadata=*/false);
case builtin_encoding::kFusedLocWithMetadata:
return readFusedLoc(reader, /*hasMetadata=*/true);
case builtin_encoding::kNameLoc:
return readNameLoc(reader);
case builtin_encoding::kUnknownLoc:
return UnknownLoc::get(getContext());
case builtin_encoding::kDenseResourceElementsAttr:
return readDenseResourceElementsAttr(reader);
case builtin_encoding::kDenseArrayAttr:
return readDenseArrayAttr(reader);
case builtin_encoding::kDenseIntOrFPElementsAttr:
return readDenseIntOrFPElementsAttr(reader);
case builtin_encoding::kDenseStringElementsAttr:
return readDenseStringElementsAttr(reader);
case builtin_encoding::kSparseElementsAttr:
return readSparseElementsAttr(reader);
default:
reader.emitError() << "unknown builtin attribute code: " << code;
return Attribute();
}
}
LogicalResult BuiltinDialectBytecodeInterface::writeAttribute(
Attribute attr, DialectBytecodeWriter &writer) const {
return TypeSwitch<Attribute, LogicalResult>(attr)
.Case<ArrayAttr, DenseArrayAttr, DenseIntOrFPElementsAttr,
DenseStringElementsAttr, DenseResourceElementsAttr, DictionaryAttr,
FloatAttr, IntegerAttr, SparseElementsAttr, StringAttr,
SymbolRefAttr, TypeAttr>([&](auto attr) {
write(attr, writer);
return success();
})
.Case<CallSiteLoc, FileLineColLoc, FusedLoc, NameLoc>([&](auto attr) {
write(attr, writer);
return success();
})
.Case([&](OpaqueLoc attr) { return write(attr, writer); })
.Case([&](UnitAttr) {
writer.writeVarInt(builtin_encoding::kUnitAttr);
return success();
})
.Case([&](UnknownLoc) {
writer.writeVarInt(builtin_encoding::kUnknownLoc);
return success();
})
.Default([&](Attribute) { return failure(); });
}
//===----------------------------------------------------------------------===//
// ArrayAttr
ArrayAttr BuiltinDialectBytecodeInterface::readArrayAttr(
DialectBytecodeReader &reader) const {
SmallVector<Attribute> elements;
if (failed(reader.readAttributes(elements)))
return ArrayAttr();
return ArrayAttr::get(getContext(), elements);
}
void BuiltinDialectBytecodeInterface::write(
ArrayAttr attr, DialectBytecodeWriter &writer) const {
writer.writeVarInt(builtin_encoding::kArrayAttr);
writer.writeAttributes(attr.getValue());
}
//===----------------------------------------------------------------------===//
// DenseArrayAttr
DenseArrayAttr BuiltinDialectBytecodeInterface::readDenseArrayAttr(
DialectBytecodeReader &reader) const {
Type elementType;
uint64_t size;
ArrayRef<char> blob;
if (failed(reader.readType(elementType)) || failed(reader.readVarInt(size)) ||
failed(reader.readBlob(blob)))
return DenseArrayAttr();
return DenseArrayAttr::get(elementType, size, blob);
}
void BuiltinDialectBytecodeInterface::write(
DenseArrayAttr attr, DialectBytecodeWriter &writer) const {
writer.writeVarInt(builtin_encoding::kDenseArrayAttr);
writer.writeType(attr.getElementType());
writer.writeVarInt(attr.getSize());
writer.writeOwnedBlob(attr.getRawData());
}
//===----------------------------------------------------------------------===//
// DenseIntOrFPElementsAttr
DenseElementsAttr BuiltinDialectBytecodeInterface::readDenseIntOrFPElementsAttr(
DialectBytecodeReader &reader) const {
ShapedType type;
ArrayRef<char> blob;
if (failed(reader.readType(type)) || failed(reader.readBlob(blob)))
return DenseIntOrFPElementsAttr();
return DenseIntOrFPElementsAttr::getFromRawBuffer(type, blob);
}
void BuiltinDialectBytecodeInterface::write(
DenseIntOrFPElementsAttr attr, DialectBytecodeWriter &writer) const {
writer.writeVarInt(builtin_encoding::kDenseIntOrFPElementsAttr);
writer.writeType(attr.getType());
writer.writeOwnedBlob(attr.getRawData());
}
//===----------------------------------------------------------------------===//
// DenseStringElementsAttr
DenseStringElementsAttr
BuiltinDialectBytecodeInterface::readDenseStringElementsAttr(
DialectBytecodeReader &reader) const {
ShapedType type;
uint64_t isSplat;
if (failed(reader.readType(type)) || failed(reader.readVarInt(isSplat)))
return DenseStringElementsAttr();
SmallVector<StringRef> values(isSplat ? 1 : type.getNumElements());
for (StringRef &value : values)
if (failed(reader.readString(value)))
return DenseStringElementsAttr();
return DenseStringElementsAttr::get(type, values);
}
void BuiltinDialectBytecodeInterface::write(
DenseStringElementsAttr attr, DialectBytecodeWriter &writer) const {
writer.writeVarInt(builtin_encoding::kDenseStringElementsAttr);
writer.writeType(attr.getType());
bool isSplat = attr.isSplat();
writer.writeVarInt(isSplat);
// If the attribute is a splat, only write out the single value.
if (isSplat)
return writer.writeOwnedString(attr.getRawStringData().front());
for (StringRef str : attr.getRawStringData())
writer.writeOwnedString(str);
}
//===----------------------------------------------------------------------===//
// DenseResourceElementsAttr
DenseResourceElementsAttr
BuiltinDialectBytecodeInterface::readDenseResourceElementsAttr(
DialectBytecodeReader &reader) const {
ShapedType type;
if (failed(reader.readType(type)))
return DenseResourceElementsAttr();
FailureOr<DenseResourceElementsHandle> handle =
reader.readResourceHandle<DenseResourceElementsHandle>();
if (failed(handle))
return DenseResourceElementsAttr();
return DenseResourceElementsAttr::get(type, *handle);
}
void BuiltinDialectBytecodeInterface::write(
DenseResourceElementsAttr attr, DialectBytecodeWriter &writer) const {
writer.writeVarInt(builtin_encoding::kDenseResourceElementsAttr);
writer.writeType(attr.getType());
writer.writeResourceHandle(attr.getRawHandle());
}
//===----------------------------------------------------------------------===//
// DictionaryAttr
DictionaryAttr BuiltinDialectBytecodeInterface::readDictionaryAttr(
DialectBytecodeReader &reader) const {
auto readNamedAttr = [&]() -> FailureOr<NamedAttribute> {
StringAttr name;
Attribute value;
if (failed(reader.readAttribute(name)) ||
failed(reader.readAttribute(value)))
return failure();
return NamedAttribute(name, value);
};
SmallVector<NamedAttribute> attrs;
if (failed(reader.readList(attrs, readNamedAttr)))
return DictionaryAttr();
return DictionaryAttr::get(getContext(), attrs);
}
void BuiltinDialectBytecodeInterface::write(
DictionaryAttr attr, DialectBytecodeWriter &writer) const {
writer.writeVarInt(builtin_encoding::kDictionaryAttr);
writer.writeList(attr.getValue(), [&](NamedAttribute attr) {
writer.writeAttribute(attr.getName());
writer.writeAttribute(attr.getValue());
});
}
//===----------------------------------------------------------------------===//
// FloatAttr
FloatAttr BuiltinDialectBytecodeInterface::readFloatAttr(
DialectBytecodeReader &reader) const {
FloatType type;
if (failed(reader.readType(type)))
return FloatAttr();
FailureOr<APFloat> value =
reader.readAPFloatWithKnownSemantics(type.getFloatSemantics());
if (failed(value))
return FloatAttr();
return FloatAttr::get(type, *value);
}
void BuiltinDialectBytecodeInterface::write(
FloatAttr attr, DialectBytecodeWriter &writer) const {
writer.writeVarInt(builtin_encoding::kFloatAttr);
writer.writeType(attr.getType());
writer.writeAPFloatWithKnownSemantics(attr.getValue());
}
//===----------------------------------------------------------------------===//
// IntegerAttr
IntegerAttr BuiltinDialectBytecodeInterface::readIntegerAttr(
DialectBytecodeReader &reader) const {
Type type;
if (failed(reader.readType(type)))
return IntegerAttr();
// Extract the value storage width from the type.
unsigned bitWidth;
if (auto intType = type.dyn_cast<IntegerType>()) {
bitWidth = intType.getWidth();
} else if (type.isa<IndexType>()) {
bitWidth = IndexType::kInternalStorageBitWidth;
} else {
reader.emitError()
<< "expected integer or index type for IntegerAttr, but got: " << type;
return IntegerAttr();
}
FailureOr<APInt> value = reader.readAPIntWithKnownWidth(bitWidth);
if (failed(value))
return IntegerAttr();
return IntegerAttr::get(type, *value);
}
void BuiltinDialectBytecodeInterface::write(
IntegerAttr attr, DialectBytecodeWriter &writer) const {
writer.writeVarInt(builtin_encoding::kIntegerAttr);
writer.writeType(attr.getType());
writer.writeAPIntWithKnownWidth(attr.getValue());
}
//===----------------------------------------------------------------------===//
// SparseElementsAttr
SparseElementsAttr BuiltinDialectBytecodeInterface::readSparseElementsAttr(
DialectBytecodeReader &reader) const {
ShapedType type;
DenseIntElementsAttr indices;
DenseElementsAttr values;
if (failed(reader.readType(type)) || failed(reader.readAttribute(indices)) ||
failed(reader.readAttribute(values)))
return SparseElementsAttr();
return SparseElementsAttr::get(type, indices, values);
}
void BuiltinDialectBytecodeInterface::write(
SparseElementsAttr attr, DialectBytecodeWriter &writer) const {
writer.writeVarInt(builtin_encoding::kSparseElementsAttr);
writer.writeType(attr.getType());
writer.writeAttribute(attr.getIndices());
writer.writeAttribute(attr.getValues());
}
//===----------------------------------------------------------------------===//
// StringAttr
StringAttr
BuiltinDialectBytecodeInterface::readStringAttr(DialectBytecodeReader &reader,
bool hasType) const {
StringRef string;
if (failed(reader.readString(string)))
return StringAttr();
// Read the type if present.
Type type;
if (!hasType)
type = NoneType::get(getContext());
else if (failed(reader.readType(type)))
return StringAttr();
return StringAttr::get(string, type);
}
void BuiltinDialectBytecodeInterface::write(
StringAttr attr, DialectBytecodeWriter &writer) const {
// We only encode the type if it isn't NoneType, which is significantly less
// common.
Type type = attr.getType();
if (!type.isa<NoneType>()) {
writer.writeVarInt(builtin_encoding::kStringAttrWithType);
writer.writeOwnedString(attr.getValue());
writer.writeType(type);
return;
}
writer.writeVarInt(builtin_encoding::kStringAttr);
writer.writeOwnedString(attr.getValue());
}
//===----------------------------------------------------------------------===//
// SymbolRefAttr
SymbolRefAttr BuiltinDialectBytecodeInterface::readSymbolRefAttr(
DialectBytecodeReader &reader, bool hasNestedRefs) const {
StringAttr rootReference;
if (failed(reader.readAttribute(rootReference)))
return SymbolRefAttr();
SmallVector<FlatSymbolRefAttr> nestedReferences;
if (hasNestedRefs && failed(reader.readAttributes(nestedReferences)))
return SymbolRefAttr();
return SymbolRefAttr::get(rootReference, nestedReferences);
}
void BuiltinDialectBytecodeInterface::write(
SymbolRefAttr attr, DialectBytecodeWriter &writer) const {
ArrayRef<FlatSymbolRefAttr> nestedRefs = attr.getNestedReferences();
writer.writeVarInt(nestedRefs.empty() ? builtin_encoding::kFlatSymbolRefAttr
: builtin_encoding::kSymbolRefAttr);
writer.writeAttribute(attr.getRootReference());
if (!nestedRefs.empty())
writer.writeAttributes(nestedRefs);
}
//===----------------------------------------------------------------------===//
// TypeAttr
TypeAttr BuiltinDialectBytecodeInterface::readTypeAttr(
DialectBytecodeReader &reader) const {
Type type;
if (failed(reader.readType(type)))
return TypeAttr();
return TypeAttr::get(type);
}
void BuiltinDialectBytecodeInterface::write(
TypeAttr attr, DialectBytecodeWriter &writer) const {
writer.writeVarInt(builtin_encoding::kTypeAttr);
writer.writeType(attr.getValue());
}
//===----------------------------------------------------------------------===//
// CallSiteLoc
LocationAttr BuiltinDialectBytecodeInterface::readCallSiteLoc(
DialectBytecodeReader &reader) const {
LocationAttr callee, caller;
if (failed(reader.readAttribute(callee)) ||
failed(reader.readAttribute(caller)))
return LocationAttr();
return CallSiteLoc::get(callee, caller);
}
void BuiltinDialectBytecodeInterface::write(
CallSiteLoc attr, DialectBytecodeWriter &writer) const {
writer.writeVarInt(builtin_encoding::kCallSiteLoc);
writer.writeAttribute(attr.getCallee());
writer.writeAttribute(attr.getCaller());
}
//===----------------------------------------------------------------------===//
// FileLineColLoc
LocationAttr BuiltinDialectBytecodeInterface::readFileLineColLoc(
DialectBytecodeReader &reader) const {
StringAttr filename;
uint64_t line, column;
if (failed(reader.readAttribute(filename)) ||
failed(reader.readVarInt(line)) || failed(reader.readVarInt(column)))
return LocationAttr();
return FileLineColLoc::get(filename, line, column);
}
void BuiltinDialectBytecodeInterface::write(
FileLineColLoc attr, DialectBytecodeWriter &writer) const {
writer.writeVarInt(builtin_encoding::kFileLineColLoc);
writer.writeAttribute(attr.getFilename());
writer.writeVarInt(attr.getLine());
writer.writeVarInt(attr.getColumn());
}
//===----------------------------------------------------------------------===//
// FusedLoc
LocationAttr
BuiltinDialectBytecodeInterface::readFusedLoc(DialectBytecodeReader &reader,
bool hasMetadata) const {
// Parse the child locations.
auto readLoc = [&]() -> FailureOr<Location> {
LocationAttr locAttr;
if (failed(reader.readAttribute(locAttr)))
return failure();
return Location(locAttr);
};
SmallVector<Location> locations;
if (failed(reader.readList(locations, readLoc)))
return LocationAttr();
// Parse the metadata if present.
Attribute metadata;
if (hasMetadata && failed(reader.readAttribute(metadata)))
return LocationAttr();
return FusedLoc::get(locations, metadata, getContext());
}
void BuiltinDialectBytecodeInterface::write(
FusedLoc attr, DialectBytecodeWriter &writer) const {
if (Attribute metadata = attr.getMetadata()) {
writer.writeVarInt(builtin_encoding::kFusedLocWithMetadata);
writer.writeAttributes(attr.getLocations());
writer.writeAttribute(metadata);
} else {
writer.writeVarInt(builtin_encoding::kFusedLoc);
writer.writeAttributes(attr.getLocations());
}
}
//===----------------------------------------------------------------------===//
// NameLoc
LocationAttr BuiltinDialectBytecodeInterface::readNameLoc(
DialectBytecodeReader &reader) const {
StringAttr name;
LocationAttr childLoc;
if (failed(reader.readAttribute(name)) ||
failed(reader.readAttribute(childLoc)))
return LocationAttr();
return NameLoc::get(name, childLoc);
}
void BuiltinDialectBytecodeInterface::write(
NameLoc attr, DialectBytecodeWriter &writer) const {
writer.writeVarInt(builtin_encoding::kNameLoc);
writer.writeAttribute(attr.getName());
writer.writeAttribute(attr.getChildLoc());
}
//===----------------------------------------------------------------------===//
// OpaqueLoc
LogicalResult
BuiltinDialectBytecodeInterface::write(OpaqueLoc attr,
DialectBytecodeWriter &writer) const {
// We can't encode an OpaqueLoc directly given that it is in-memory only, so
// encode the fallback instead.
return writeAttribute(attr.getFallbackLocation(), writer);
}
//===----------------------------------------------------------------------===//
// Types
//===----------------------------------------------------------------------===//
Type BuiltinDialectBytecodeInterface::readType(
DialectBytecodeReader &reader) const {
uint64_t code;
if (failed(reader.readVarInt(code)))
return Type();
switch (code) {
case builtin_encoding::kIntegerType:
return readIntegerType(reader);
case builtin_encoding::kIndexType:
return IndexType::get(getContext());
case builtin_encoding::kFunctionType:
return readFunctionType(reader);
case builtin_encoding::kBFloat16Type:
return BFloat16Type::get(getContext());
case builtin_encoding::kFloat16Type:
return Float16Type::get(getContext());
case builtin_encoding::kFloat32Type:
return Float32Type::get(getContext());
case builtin_encoding::kFloat64Type:
return Float64Type::get(getContext());
case builtin_encoding::kFloat80Type:
return Float80Type::get(getContext());
case builtin_encoding::kFloat128Type:
return Float128Type::get(getContext());
case builtin_encoding::kComplexType:
return readComplexType(reader);
case builtin_encoding::kMemRefType:
return readMemRefType(reader, /*hasMemSpace=*/false);
case builtin_encoding::kMemRefTypeWithMemSpace:
return readMemRefType(reader, /*hasMemSpace=*/true);
case builtin_encoding::kNoneType:
return NoneType::get(getContext());
case builtin_encoding::kRankedTensorType:
return readRankedTensorType(reader, /*hasEncoding=*/false);
case builtin_encoding::kRankedTensorTypeWithEncoding:
return readRankedTensorType(reader, /*hasEncoding=*/true);
case builtin_encoding::kTupleType:
return readTupleType(reader);
case builtin_encoding::kUnrankedMemRefType:
return readUnrankedMemRefType(reader, /*hasMemSpace=*/false);
case builtin_encoding::kUnrankedMemRefTypeWithMemSpace:
return readUnrankedMemRefType(reader, /*hasMemSpace=*/true);
case builtin_encoding::kUnrankedTensorType:
return readUnrankedTensorType(reader);
case builtin_encoding::kVectorType:
return readVectorType(reader, /*hasScalableDims=*/false);
case builtin_encoding::kVectorTypeWithScalableDims:
return readVectorType(reader, /*hasScalableDims=*/true);
default:
reader.emitError() << "unknown builtin type code: " << code;
return Type();
}
}
LogicalResult BuiltinDialectBytecodeInterface::writeType(
Type type, DialectBytecodeWriter &writer) const {
return TypeSwitch<Type, LogicalResult>(type)
.Case<ComplexType, IntegerType, FunctionType, MemRefType,
RankedTensorType, TupleType, UnrankedMemRefType, UnrankedTensorType,
VectorType>([&](auto type) {
write(type, writer);
return success();
})
.Case([&](IndexType) {
return writer.writeVarInt(builtin_encoding::kIndexType), success();
})
.Case([&](BFloat16Type) {
return writer.writeVarInt(builtin_encoding::kBFloat16Type), success();
})
.Case([&](Float16Type) {
return writer.writeVarInt(builtin_encoding::kFloat16Type), success();
})
.Case([&](Float32Type) {
return writer.writeVarInt(builtin_encoding::kFloat32Type), success();
})
.Case([&](Float64Type) {
return writer.writeVarInt(builtin_encoding::kFloat64Type), success();
})
.Case([&](Float80Type) {
return writer.writeVarInt(builtin_encoding::kFloat80Type), success();
})
.Case([&](Float128Type) {
return writer.writeVarInt(builtin_encoding::kFloat128Type), success();
})
.Case([&](NoneType) {
return writer.writeVarInt(builtin_encoding::kNoneType), success();
})
.Default([&](Type) { return failure(); });
}
//===----------------------------------------------------------------------===//
// ComplexType
ComplexType BuiltinDialectBytecodeInterface::readComplexType(
DialectBytecodeReader &reader) const {
Type elementType;
if (failed(reader.readType(elementType)))
return ComplexType();
return ComplexType::get(elementType);
}
void BuiltinDialectBytecodeInterface::write(
ComplexType type, DialectBytecodeWriter &writer) const {
writer.writeVarInt(builtin_encoding::kComplexType);
writer.writeType(type.getElementType());
}
//===----------------------------------------------------------------------===//
// IntegerType
IntegerType BuiltinDialectBytecodeInterface::readIntegerType(
DialectBytecodeReader &reader) const {
uint64_t encoding;
if (failed(reader.readVarInt(encoding)))
return IntegerType();
return IntegerType::get(
getContext(), encoding >> 2,
static_cast<IntegerType::SignednessSemantics>(encoding & 0x3));
}
void BuiltinDialectBytecodeInterface::write(
IntegerType type, DialectBytecodeWriter &writer) const {
writer.writeVarInt(builtin_encoding::kIntegerType);
writer.writeVarInt((type.getWidth() << 2) | type.getSignedness());
}
//===----------------------------------------------------------------------===//
// FunctionType
FunctionType BuiltinDialectBytecodeInterface::readFunctionType(
DialectBytecodeReader &reader) const {
SmallVector<Type> inputs, results;
if (failed(reader.readTypes(inputs)) || failed(reader.readTypes(results)))
return FunctionType();
return FunctionType::get(getContext(), inputs, results);
}
void BuiltinDialectBytecodeInterface::write(
FunctionType type, DialectBytecodeWriter &writer) const {
writer.writeVarInt(builtin_encoding::kFunctionType);
writer.writeTypes(type.getInputs());
writer.writeTypes(type.getResults());
}
//===----------------------------------------------------------------------===//
// MemRefType
MemRefType
BuiltinDialectBytecodeInterface::readMemRefType(DialectBytecodeReader &reader,
bool hasMemSpace) const {
Attribute memorySpace;
if (hasMemSpace && failed(reader.readAttribute(memorySpace)))
return MemRefType();
SmallVector<int64_t> shape;
Type elementType;
MemRefLayoutAttrInterface layout;
if (failed(reader.readSignedVarInts(shape)) ||
failed(reader.readType(elementType)) ||
failed(reader.readAttribute(layout)))
return MemRefType();
return MemRefType::get(shape, elementType, layout, memorySpace);
}
void BuiltinDialectBytecodeInterface::write(
MemRefType type, DialectBytecodeWriter &writer) const {
if (Attribute memSpace = type.getMemorySpace()) {
writer.writeVarInt(builtin_encoding::kMemRefTypeWithMemSpace);
writer.writeAttribute(memSpace);
} else {
writer.writeVarInt(builtin_encoding::kMemRefType);
}
writer.writeSignedVarInts(type.getShape());
writer.writeType(type.getElementType());
writer.writeAttribute(type.getLayout());
}
//===----------------------------------------------------------------------===//
// RankedTensorType
RankedTensorType BuiltinDialectBytecodeInterface::readRankedTensorType(
DialectBytecodeReader &reader, bool hasEncoding) const {
Attribute encoding;
if (hasEncoding && failed(reader.readAttribute(encoding)))
return RankedTensorType();
SmallVector<int64_t> shape;
Type elementType;
if (failed(reader.readSignedVarInts(shape)) ||
failed(reader.readType(elementType)))
return RankedTensorType();
return RankedTensorType::get(shape, elementType, encoding);
}
void BuiltinDialectBytecodeInterface::write(
RankedTensorType type, DialectBytecodeWriter &writer) const {
if (Attribute encoding = type.getEncoding()) {
writer.writeVarInt(builtin_encoding::kRankedTensorTypeWithEncoding);
writer.writeAttribute(encoding);
} else {
writer.writeVarInt(builtin_encoding::kRankedTensorType);
}
writer.writeSignedVarInts(type.getShape());
writer.writeType(type.getElementType());
}
//===----------------------------------------------------------------------===//
// TupleType
TupleType BuiltinDialectBytecodeInterface::readTupleType(
DialectBytecodeReader &reader) const {
SmallVector<Type> elements;
if (failed(reader.readTypes(elements)))
return TupleType();
return TupleType::get(getContext(), elements);
}
void BuiltinDialectBytecodeInterface::write(
TupleType type, DialectBytecodeWriter &writer) const {
writer.writeVarInt(builtin_encoding::kTupleType);
writer.writeTypes(type.getTypes());
}
//===----------------------------------------------------------------------===//
// UnrankedMemRefType
UnrankedMemRefType BuiltinDialectBytecodeInterface::readUnrankedMemRefType(
DialectBytecodeReader &reader, bool hasMemSpace) const {
Attribute memorySpace;
if (hasMemSpace && failed(reader.readAttribute(memorySpace)))
return UnrankedMemRefType();
Type elementType;
if (failed(reader.readType(elementType)))
return UnrankedMemRefType();
return UnrankedMemRefType::get(elementType, memorySpace);
}
void BuiltinDialectBytecodeInterface::write(
UnrankedMemRefType type, DialectBytecodeWriter &writer) const {
if (Attribute memSpace = type.getMemorySpace()) {
writer.writeVarInt(builtin_encoding::kUnrankedMemRefTypeWithMemSpace);
writer.writeAttribute(memSpace);
} else {
writer.writeVarInt(builtin_encoding::kUnrankedMemRefType);
}
writer.writeType(type.getElementType());
}
//===----------------------------------------------------------------------===//
// UnrankedTensorType
UnrankedTensorType BuiltinDialectBytecodeInterface::readUnrankedTensorType(
DialectBytecodeReader &reader) const {
Type elementType;
if (failed(reader.readType(elementType)))
return UnrankedTensorType();
return UnrankedTensorType::get(elementType);
}
void BuiltinDialectBytecodeInterface::write(
UnrankedTensorType type, DialectBytecodeWriter &writer) const {
writer.writeVarInt(builtin_encoding::kUnrankedTensorType);
writer.writeType(type.getElementType());
}
//===----------------------------------------------------------------------===//
// VectorType
VectorType
BuiltinDialectBytecodeInterface::readVectorType(DialectBytecodeReader &reader,
bool hasScalableDims) const {
uint64_t numScalableDims = 0;
if (hasScalableDims && failed(reader.readVarInt(numScalableDims)))
return VectorType();
SmallVector<int64_t> shape;
Type elementType;
if (failed(reader.readSignedVarInts(shape)) ||
failed(reader.readType(elementType)))
return VectorType();
return VectorType::get(shape, elementType, numScalableDims);
}
void BuiltinDialectBytecodeInterface::write(
VectorType type, DialectBytecodeWriter &writer) const {
if (unsigned numScalableDims = type.getNumScalableDims()) {
writer.writeVarInt(builtin_encoding::kVectorTypeWithScalableDims);
writer.writeVarInt(numScalableDims);
} else {
writer.writeVarInt(builtin_encoding::kVectorType);
}
writer.writeSignedVarInts(type.getShape());
writer.writeType(type.getElementType());
}