llvm-project/mlir/lib/IR/BuiltinDialectBytecode.cpp
Jacques Pienaar 01e75646a5
[mlir] Add FileRange location type. (#80213)
This location type represents a contiguous range inside a file. It is
effectively a pair of FileLineCols. Add new type and make FileLineCol a
view for case where it matches existing previous one.

The location includes filename and optional start line & col, and end
line & col. Considered common cases are file:line, file:line:col,
file:line:start_col to file:line:end_col and general range within same
file. In memory its encoded as trailing objects. This keeps the memory
requirement the same as FileLineColLoc today (makes the rather common
File:Line cheaper) at the expense of extra work at decoding time. Kept the unsigned
type.

There was the option to always have file range be castable to
FileLineColLoc. This cast would just drop other fields. That may result
in some simpler staging. TBD.

This is a rather minimal change, it does not yet add bindings (C or
Python), lowering to LLVM debug locations etc. that supports end line:cols.

---------

Co-authored-by: River Riddle <riddleriver@gmail.com>
2024-11-23 05:12:04 -08:00

186 lines
6.2 KiB
C++

//===- 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 "AttributeDetail.h"
#include "mlir/Bytecode/BytecodeImplementation.h"
#include "mlir/IR/BuiltinAttributes.h"
#include "mlir/IR/BuiltinDialect.h"
#include "mlir/IR/BuiltinTypes.h"
#include "mlir/IR/Diagnostics.h"
#include "mlir/IR/DialectResourceBlobManager.h"
#include "mlir/IR/Location.h"
#include "mlir/Support/LLVM.h"
#include "llvm/ADT/TypeSwitch.h"
#include <cstdint>
using namespace mlir;
//===----------------------------------------------------------------------===//
// BuiltinDialectBytecodeInterface
//===----------------------------------------------------------------------===//
namespace {
//===----------------------------------------------------------------------===//
// Utility functions
// TODO: Move these to separate file.
// Returns the bitwidth if known, else return 0.
static unsigned getIntegerBitWidth(DialectBytecodeReader &reader, Type type) {
if (auto intType = dyn_cast<IntegerType>(type)) {
return intType.getWidth();
}
if (llvm::isa<IndexType>(type)) {
return IndexType::kInternalStorageBitWidth;
}
reader.emitError()
<< "expected integer or index type for IntegerAttr, but got: " << type;
return 0;
}
static LogicalResult readAPIntWithKnownWidth(DialectBytecodeReader &reader,
Type type, FailureOr<APInt> &val) {
unsigned bitWidth = getIntegerBitWidth(reader, type);
val = reader.readAPIntWithKnownWidth(bitWidth);
return val;
}
static LogicalResult
readAPFloatWithKnownSemantics(DialectBytecodeReader &reader, Type type,
FailureOr<APFloat> &val) {
auto ftype = dyn_cast<FloatType>(type);
if (!ftype)
return failure();
val = reader.readAPFloatWithKnownSemantics(ftype.getFloatSemantics());
return success();
}
LogicalResult
readPotentiallySplatString(DialectBytecodeReader &reader, ShapedType type,
bool isSplat,
SmallVectorImpl<StringRef> &rawStringData) {
rawStringData.resize(isSplat ? 1 : type.getNumElements());
for (StringRef &value : rawStringData)
if (failed(reader.readString(value)))
return failure();
return success();
}
static void writePotentiallySplatString(DialectBytecodeWriter &writer,
DenseStringElementsAttr attr) {
bool isSplat = attr.isSplat();
if (isSplat)
return writer.writeOwnedString(attr.getRawStringData().front());
for (StringRef str : attr.getRawStringData())
writer.writeOwnedString(str);
}
static FileLineColRange getFileLineColRange(MLIRContext *context,
StringAttr filename,
ArrayRef<uint64_t> lineCols) {
switch (lineCols.size()) {
case 0:
return FileLineColRange::get(filename);
case 1:
return FileLineColRange::get(filename, lineCols[0]);
case 2:
return FileLineColRange::get(filename, lineCols[0], lineCols[1]);
case 3:
return FileLineColRange::get(filename, lineCols[0], lineCols[1],
lineCols[2]);
case 4:
return FileLineColRange::get(filename, lineCols[0], lineCols[1],
lineCols[2], lineCols[3]);
default:
return {};
}
}
static LogicalResult
readFileLineColRangeLocs(DialectBytecodeReader &reader,
SmallVectorImpl<uint64_t> &lineCols) {
return reader.readList(
lineCols, [&reader](uint64_t &val) { return reader.readVarInt(val); });
}
static void writeFileLineColRangeLocs(DialectBytecodeWriter &writer,
FileLineColRange range) {
if (range.getStartLine() == 0 && range.getStartColumn() == 0 &&
range.getEndLine() == 0 && range.getEndColumn() == 0) {
writer.writeVarInt(0);
return;
}
if (range.getStartColumn() == 0 &&
range.getStartLine() == range.getEndLine()) {
writer.writeVarInt(1);
writer.writeVarInt(range.getStartLine());
return;
}
// The single file:line:col is handled by other writer, but checked here for
// completeness.
if (range.getEndColumn() == range.getStartColumn() &&
range.getStartLine() == range.getEndLine()) {
writer.writeVarInt(2);
writer.writeVarInt(range.getStartLine());
writer.writeVarInt(range.getStartColumn());
return;
}
if (range.getStartLine() == range.getEndLine()) {
writer.writeVarInt(3);
writer.writeVarInt(range.getStartLine());
writer.writeVarInt(range.getStartColumn());
writer.writeVarInt(range.getEndColumn());
return;
}
writer.writeVarInt(4);
writer.writeVarInt(range.getStartLine());
writer.writeVarInt(range.getStartColumn());
writer.writeVarInt(range.getEndLine());
writer.writeVarInt(range.getEndColumn());
}
#include "mlir/IR/BuiltinDialectBytecode.cpp.inc"
/// 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 {
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 builtin_dialect_detail::addBytecodeInterface(BuiltinDialect *dialect) {
dialect->addInterfaces<BuiltinDialectBytecodeInterface>();
}