forked from OSchip/llvm-project
Add GDB prettyprinters for a few more MLIR types.
Reviewed By: dblaikie, jpienaar Differential Revision: https://reviews.llvm.org/D87159
This commit is contained in:
parent
1b60f63e4f
commit
e9b3884161
|
@ -22,6 +22,16 @@ set(DEBUGINFO_TEST_DEPS
|
|||
not
|
||||
)
|
||||
|
||||
if ("mlir" IN_LIST LLVM_ENABLE_PROJECTS)
|
||||
add_llvm_executable(check-gdb-mlir-support
|
||||
llvm-prettyprinters/gdb/mlir-support.cpp
|
||||
)
|
||||
target_include_directories(check-gdb-mlir-support PRIVATE ${LLVM_EXTERNAL_MLIR_SOURCE_DIR}/include)
|
||||
target_link_libraries(check-gdb-mlir-support PRIVATE MLIRIR)
|
||||
list(APPEND DEBUGINFO_TEST_DEPS check-gdb-mlir-support)
|
||||
set(MLIR_SOURCE_DIR ${LLVM_EXTERNAL_MLIR_SOURCE_DIR})
|
||||
endif()
|
||||
|
||||
if("compiler-rt" IN_LIST LLVM_ENABLE_PROJECTS)
|
||||
# llgdb-tests/asan.c and other asan* files.
|
||||
if(TARGET asan)
|
||||
|
|
|
@ -157,6 +157,6 @@ if platform.system() == 'Darwin':
|
|||
if apple_lldb_vers < 1000:
|
||||
config.available_features.add('apple-lldb-pre-1000')
|
||||
|
||||
llvm_config.feature_config([('--build-mode', {
|
||||
'Debug|RelWithDebInfo': 'debug-info'
|
||||
})])
|
||||
llvm_config.feature_config(
|
||||
[('--build-mode', {'Debug|RelWithDebInfo': 'debug-info'})]
|
||||
)
|
||||
|
|
|
@ -20,6 +20,8 @@ config.target_triple = "@TARGET_TRIPLE@"
|
|||
config.host_arch = "@HOST_ARCH@"
|
||||
config.is_msvc = lit.util.pythonize_bool("@MSVC@")
|
||||
|
||||
config.mlir_src_root = "@MLIR_SOURCE_DIR@"
|
||||
|
||||
config.llvm_use_sanitizer = "@LLVM_USE_SANITIZER@"
|
||||
|
||||
config.python3_executable = "@Python3_EXECUTABLE@"
|
||||
|
|
|
@ -4,6 +4,10 @@ import lit.util
|
|||
if 'native' not in config.available_features or lit.util.which('gdb') is None:
|
||||
config.unsupported = True
|
||||
|
||||
if config.mlir_src_root:
|
||||
config.substitutions.append(("%mlir_src_root", config.mlir_src_root))
|
||||
config.available_features.add('mlir')
|
||||
|
||||
config.suffixes = ['.gdb']
|
||||
|
||||
|
||||
|
|
|
@ -53,8 +53,13 @@ auto SimpleIlist = []() {
|
|||
return Result;
|
||||
}();
|
||||
|
||||
// Check expected instances to avoid compile errors.
|
||||
auto CheckExpectedValue = static_cast<bool>(ExpectedValue);
|
||||
auto CheckExpectedError = static_cast<bool>(ExpectedError);
|
||||
|
||||
int main() { return 0; }
|
||||
int main() {
|
||||
// Reference symbols that might otherwise be stripped.
|
||||
ArrayRef[0];
|
||||
MutableArrayRef[0];
|
||||
!ExpectedValue;
|
||||
!ExpectedError;
|
||||
*OptionalValue;
|
||||
*OptionalNone;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
#include "mlir/IR/Identifier.h"
|
||||
#include "mlir/IR/Location.h"
|
||||
#include "mlir/IR/MLIRContext.h"
|
||||
#include "mlir/IR/OperationSupport.h"
|
||||
#include "mlir/IR/StandardTypes.h"
|
||||
|
||||
mlir::MLIRContext Context;
|
||||
|
||||
auto Identifier = mlir::Identifier::get("foo", &Context);
|
||||
mlir::OperationName OperationName("FooOp", &Context);
|
||||
mlir::Value Value({reinterpret_cast<void *>(0x8),
|
||||
mlir::Value::Kind::TrailingOpResult});
|
||||
|
||||
mlir::Type Type(nullptr);
|
||||
mlir::Type IndexType = mlir::IndexType::get(&Context);
|
||||
mlir::Type IntegerType =
|
||||
mlir::IntegerType::get(3, mlir::IntegerType::Unsigned, &Context);
|
||||
mlir::Type FloatType = mlir::Float32Type::get(&Context);
|
||||
mlir::Type MemRefType = mlir::MemRefType::get({4, 5}, FloatType);
|
||||
mlir::Type UnrankedMemRefType = mlir::UnrankedMemRefType::get(IntegerType, 6);
|
||||
mlir::Type VectorType = mlir::VectorType::get({1, 2}, FloatType);
|
||||
mlir::Type TupleType =
|
||||
mlir::TupleType::get(mlir::TypeRange({IndexType, FloatType}), &Context);
|
||||
|
||||
auto UnknownLoc = mlir::UnknownLoc::get(&Context);
|
||||
auto FileLineColLoc = mlir::FileLineColLoc::get("file", 7, 8, &Context);
|
||||
auto OpaqueLoc = mlir::OpaqueLoc::get<uintptr_t>(9, &Context);
|
||||
auto NameLoc = mlir::NameLoc::get(Identifier, &Context);
|
||||
auto CallSiteLoc = mlir::CallSiteLoc::get(FileLineColLoc, OpaqueLoc);
|
||||
auto FusedLoc = mlir::FusedLoc::get({FileLineColLoc, NameLoc}, &Context);
|
||||
|
||||
mlir::Attribute UnitAttr = mlir::UnitAttr::get(&Context);
|
||||
mlir::Attribute FloatAttr = mlir::FloatAttr::get(FloatType, 1.0);
|
||||
mlir::Attribute IntegerAttr = mlir::IntegerAttr::get(IntegerType, 10);
|
||||
mlir::Attribute TypeAttr = mlir::TypeAttr::get(IndexType);
|
||||
mlir::Attribute ArrayAttr = mlir::ArrayAttr::get({UnitAttr}, &Context);
|
||||
mlir::Attribute StringAttr = mlir::StringAttr::get("foo", &Context);
|
||||
mlir::Attribute ElementsAttr = mlir::DenseElementsAttr::get(
|
||||
VectorType.cast<mlir::ShapedType>(), llvm::ArrayRef<float>{2.0f, 3.0f});
|
||||
|
||||
int main() { return 0; }
|
|
@ -0,0 +1,112 @@
|
|||
# RUN: gdb -q -batch -n -iex 'source %mlir_src_root/utils/gdb-scripts/prettyprinters.py' -iex 'source %llvm_src_root/utils/gdb-scripts/prettyprinters.py' -x %s %llvm_tools_dir/check-gdb-mlir-support | FileCheck %s
|
||||
# REQUIRES: debug-info
|
||||
# REQUIRES: mlir
|
||||
|
||||
break main
|
||||
run
|
||||
|
||||
# CHECK: "foo"
|
||||
p Identifier
|
||||
|
||||
# CHECK: "FooOp"
|
||||
p OperationName
|
||||
|
||||
# CHECK: 0x8
|
||||
# CHECK: TrailingOpResult
|
||||
p Value
|
||||
|
||||
# CHECK: impl = 0x0
|
||||
p Type
|
||||
|
||||
# CHECK: cast<mlir::IndexType>
|
||||
p IndexType
|
||||
|
||||
# CHECK: cast<mlir::IntegerType>
|
||||
# CHECK: width = 3
|
||||
# CHECK: Unsigned
|
||||
p IntegerType
|
||||
|
||||
# CHECK: cast<mlir::Float32Type>
|
||||
p FloatType
|
||||
|
||||
# CHECK: cast<mlir::MemRefType>
|
||||
# CHECK: shapeSize = 2
|
||||
# CHECK: shapeElements[0] = 4
|
||||
# CHECK: shapeElements[1] = 5
|
||||
p MemRefType
|
||||
|
||||
# CHECK: cast<mlir::UnrankedMemRefType>
|
||||
# CHECK: memorySpace = 6
|
||||
p UnrankedMemRefType
|
||||
|
||||
# CHECK: cast<mlir::VectorType>
|
||||
# CHECK: shapeSize = 2
|
||||
# CHECK: shapeElements[0] = 1
|
||||
# CHECK: shapeElements[1] = 2
|
||||
p VectorType
|
||||
|
||||
# CHECK: cast<mlir::TupleType>
|
||||
# CHECK: numElements = 2
|
||||
# CHECK: elements[0]
|
||||
# CHECK: mlir::IndexType
|
||||
# CHECK: elements[1]
|
||||
# CHECK: mlir::Float32Type
|
||||
p TupleType
|
||||
|
||||
# CHECK: cast<mlir::UnknownLoc>
|
||||
p UnknownLoc
|
||||
|
||||
# CHECK: cast<mlir::FileLineColLoc>
|
||||
# CHECK: filename = "file"
|
||||
# CHECK: line = 7
|
||||
# CHECK: column = 8
|
||||
p FileLineColLoc
|
||||
|
||||
# CHECK: cast<mlir::OpaqueLoc>
|
||||
# CHECK: underlyingLocation = 9
|
||||
p OpaqueLoc
|
||||
|
||||
# CHECK: cast<mlir::NameLoc>
|
||||
# CHECK: name = "foo"
|
||||
# CHECK: mlir::UnknownLoc
|
||||
p NameLoc
|
||||
|
||||
# CHECK: cast<mlir::CallSiteLoc>
|
||||
# CHECK: callee
|
||||
# CHECK: mlir::FileLineColLoc
|
||||
# CHECK: caller
|
||||
# CHECK: mlir::OpaqueLoc
|
||||
p CallSiteLoc
|
||||
|
||||
# CHECK: cast<mlir::FusedLoc>
|
||||
# CHECK: numLocs = 2
|
||||
# CHECK: locs[0]
|
||||
# CHECK: mlir::FileLineColLoc
|
||||
# CHECK: locs[1]
|
||||
# CHECK: mlir::NameLoc
|
||||
p FusedLoc
|
||||
|
||||
# CHECK: cast<mlir::UnitAttr>
|
||||
p UnitAttr
|
||||
|
||||
# CHECK: cast<mlir::FloatAttr>
|
||||
p FloatAttr
|
||||
|
||||
# CHECK: cast<mlir::IntegerAttr>
|
||||
p IntegerAttr
|
||||
|
||||
# CHECK: cast<mlir::TypeAttr>
|
||||
# CHECK: mlir::IndexType
|
||||
p TypeAttr
|
||||
|
||||
# CHECK: cast<mlir::ArrayAttr>
|
||||
# CHECK: llvm::ArrayRef of length 1
|
||||
# CHECK: mlir::UnitAttr
|
||||
p ArrayAttr
|
||||
|
||||
# CHECK: cast<mlir::StringAttr>
|
||||
# CHECK: value = "foo"
|
||||
p StringAttr
|
||||
|
||||
# CHECK: cast<mlir::DenseIntOrFPElementsAttr>
|
||||
p ElementsAttr
|
|
@ -0,0 +1,235 @@
|
|||
"""GDB pretty printers for MLIR types."""
|
||||
|
||||
import gdb.printing
|
||||
|
||||
|
||||
class IdentifierPrinter:
|
||||
"""Prints an mlir::Identifier instance."""
|
||||
|
||||
def __init__(self, val):
|
||||
self.entry = val['entry']
|
||||
|
||||
def to_string(self):
|
||||
ptr = (self.entry + 1).cast(gdb.lookup_type('char').pointer())
|
||||
return ptr.string(length=self.entry['keyLength'])
|
||||
|
||||
def display_hint(self):
|
||||
return 'string'
|
||||
|
||||
|
||||
class StoragePrinter:
|
||||
"""Prints bases of a struct and its fields."""
|
||||
|
||||
def __init__(self, val):
|
||||
self.val = val
|
||||
|
||||
def children(self):
|
||||
for field in self.val.type.fields():
|
||||
if field.is_base_class:
|
||||
yield ('<%s>' % field.name, self.val.cast(field.type))
|
||||
else:
|
||||
yield (field.name, self.val[field.name])
|
||||
|
||||
|
||||
class TupleTypeStoragePrinter(StoragePrinter):
|
||||
|
||||
def children(self):
|
||||
for child in StoragePrinter.children(self):
|
||||
yield child
|
||||
pointer_type = gdb.lookup_type('mlir::Type').pointer()
|
||||
elements = (self.val.address + 1).cast(pointer_type)
|
||||
for i in range(self.val['numElements']):
|
||||
yield 'elements[%u]' % i, elements[i]
|
||||
|
||||
|
||||
class RankedTypeStoragePrinter(StoragePrinter):
|
||||
|
||||
def children(self):
|
||||
for child in StoragePrinter.children(self):
|
||||
yield child
|
||||
for i in range(self.val['shapeSize']):
|
||||
yield 'shapeElements[%u]' % i, self.val['shapeElements'][i]
|
||||
|
||||
|
||||
class MemRefTypeStoragePrinter(RankedTypeStoragePrinter):
|
||||
|
||||
def children(self):
|
||||
for child in RankedTypeStoragePrinter.children(self):
|
||||
yield child
|
||||
for i in range(self.val['numAffineMaps']):
|
||||
yield 'affineMapsList[%u]' % i, self.val['affineMapsList'][i]
|
||||
|
||||
|
||||
class FusedLocationStoragePrinter(StoragePrinter):
|
||||
|
||||
def children(self):
|
||||
for child in StoragePrinter.children(self):
|
||||
yield child
|
||||
pointer_type = gdb.lookup_type('mlir::Location').pointer()
|
||||
elements = (self.val.address + 1).cast(pointer_type)
|
||||
for i in range(self.val['numLocs']):
|
||||
yield 'locs[%u]' % i, elements[i]
|
||||
|
||||
|
||||
class StorageUserBasePrinter:
|
||||
"""Printer for an mlir::detail::StorageUserBase instance."""
|
||||
|
||||
def __init__(self, val):
|
||||
self.val = val
|
||||
|
||||
def children(self):
|
||||
storage_type = self.val.type.template_argument(2)
|
||||
yield 'impl', self.val['impl'].dereference().cast(storage_type)
|
||||
|
||||
|
||||
class StorageTypeMap:
|
||||
"""Maps a TypeID to the corresponding type derived from StorageUserBase.
|
||||
|
||||
Types need to be registered by name before the first lookup.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.map = None
|
||||
self.type_names = []
|
||||
|
||||
def register_type(self, type_name):
|
||||
assert not self.map, 'register_type called after __getitem__'
|
||||
self.type_names += [type_name]
|
||||
|
||||
def _init_map(self):
|
||||
"""Lazy initialization of self.map."""
|
||||
if self.map:
|
||||
return
|
||||
self.map = {}
|
||||
for type_name in self.type_names:
|
||||
concrete_type = gdb.lookup_type(type_name)
|
||||
storage = gdb.parse_and_eval(
|
||||
"&'mlir::TypeID::get<%s>()::instance'" % type_name)
|
||||
if concrete_type and storage:
|
||||
self.map[int(storage)] = concrete_type
|
||||
|
||||
def __getitem__(self, type_id):
|
||||
self._init_map()
|
||||
return self.map.get(int(type_id['storage']))
|
||||
|
||||
|
||||
storage_type_map = StorageTypeMap()
|
||||
|
||||
|
||||
def get_type_id_printer(val):
|
||||
"""Returns a printer of the name of a mlir::TypeID."""
|
||||
|
||||
class StringPrinter:
|
||||
|
||||
def __init__(self, string):
|
||||
self.string = string
|
||||
|
||||
def to_string(self):
|
||||
return self.string
|
||||
|
||||
concrete_type = storage_type_map[val]
|
||||
if not concrete_type:
|
||||
return None
|
||||
return StringPrinter('"%s"' % concrete_type.name)
|
||||
|
||||
|
||||
def get_attr_or_type_printer(val, get_type_id):
|
||||
"""Returns a printer for mlir::Attribute or mlir::Type."""
|
||||
|
||||
class UpcastPrinter:
|
||||
|
||||
def __init__(self, val, type):
|
||||
self.val = val.cast(type)
|
||||
|
||||
def children(self):
|
||||
yield 'cast<%s>' % self.val.type.name, self.val
|
||||
|
||||
if not val['impl']:
|
||||
return None
|
||||
type_id = get_type_id(val['impl'].dereference())
|
||||
concrete_type = storage_type_map[type_id]
|
||||
if not concrete_type:
|
||||
return None
|
||||
return UpcastPrinter(val, concrete_type)
|
||||
|
||||
|
||||
pp = gdb.printing.RegexpCollectionPrettyPrinter('MLIRSupport')
|
||||
|
||||
pp.add_printer('mlir::Identifier', '^mlir::Identifier$', IdentifierPrinter)
|
||||
|
||||
# Printers for types deriving from AttributeStorage or TypeStorage.
|
||||
pp.add_printer('mlir::detail::FusedLocationStorage',
|
||||
'^mlir::detail::FusedLocationStorage',
|
||||
FusedLocationStoragePrinter)
|
||||
pp.add_printer('mlir::detail::VectorTypeStorage',
|
||||
'^mlir::detail::VectorTypeStorage', RankedTypeStoragePrinter)
|
||||
pp.add_printer('mlir::detail::RankedTensorTypeStorage',
|
||||
'^mlir::detail::RankedTensorTypeStorage',
|
||||
RankedTypeStoragePrinter)
|
||||
pp.add_printer('mlir::detail::MemRefTypeStorage',
|
||||
'^mlir::detail::MemRefTypeStorage$', MemRefTypeStoragePrinter)
|
||||
pp.add_printer('mlir::detail::TupleTypeStorage',
|
||||
'^mlir::detail::TupleTypeStorage$', TupleTypeStoragePrinter)
|
||||
|
||||
# Printers for Attribute::AttrBase or Type::TypeBase typedefs.
|
||||
pp.add_printer('mlir::detail::StorageUserBase',
|
||||
'^mlir::detail::StorageUserBase<.*>$', StorageUserBasePrinter)
|
||||
|
||||
# Printers of types deriving from Attribute::AttrBase or Type::TypeBase.
|
||||
for name in [
|
||||
# mlir/IR/Attributes.h
|
||||
'ArrayAttr',
|
||||
'DictionaryAttr',
|
||||
'FloatAttr',
|
||||
'IntegerAttr',
|
||||
'IntegerSetAttr',
|
||||
'OpaqueAttr',
|
||||
'StringAttr',
|
||||
'SymbolRefAttr',
|
||||
'TypeAttr',
|
||||
'UnitAttr',
|
||||
'DenseStringElementsAttr',
|
||||
'DenseIntOrFPElementsAttr',
|
||||
'OpaqueElementsAttr',
|
||||
'SparseElementsAttr',
|
||||
# mlir/IR/StandardTypes.h
|
||||
'ComplexType',
|
||||
'IndexType',
|
||||
'IntegerType',
|
||||
'Float16Type',
|
||||
'Float32Type',
|
||||
'Float64Type',
|
||||
'NoneType',
|
||||
'VectorType',
|
||||
'RankedTensorType',
|
||||
'UnrankedTensorType',
|
||||
'MemRefType',
|
||||
'UnrankedMemRefType',
|
||||
'TupleType',
|
||||
# mlir/IR/Location.h
|
||||
'CallSiteLoc',
|
||||
'FileLineColLoc',
|
||||
'FusedLoc',
|
||||
'NameLoc',
|
||||
'OpaqueLoc',
|
||||
'UnknownLoc'
|
||||
]:
|
||||
storage_type_map.register_type('mlir::%s' % name) # Register for upcasting.
|
||||
|
||||
pp.add_printer('mlir::TypeID', '^mlir::TypeID$', get_type_id_printer)
|
||||
|
||||
|
||||
def add_attr_or_type_printers(name):
|
||||
"""Adds printers for mlir::Attribute or mlir::Type and their Storage type."""
|
||||
get_type_id = lambda val: val['abstract%s' % name]['typeID']
|
||||
pp.add_printer('mlir::%s' % name, '^mlir::%s$' % name,
|
||||
lambda val: get_attr_or_type_printer(val, get_type_id))
|
||||
pp.add_printer('mlir::%sStorage' % name, '^mlir::%sStorage$' % name,
|
||||
lambda val: get_type_id_printer(get_type_id(val)))
|
||||
|
||||
|
||||
# Upcasting printers of mlir::Attribute and mlir::Type.
|
||||
for name in ['Attribute', 'Type']:
|
||||
add_attr_or_type_printers(name)
|
||||
|
||||
gdb.printing.register_pretty_printer(gdb.current_objfile(), pp)
|
Loading…
Reference in New Issue