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
|
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)
|
if("compiler-rt" IN_LIST LLVM_ENABLE_PROJECTS)
|
||||||
# llgdb-tests/asan.c and other asan* files.
|
# llgdb-tests/asan.c and other asan* files.
|
||||||
if(TARGET asan)
|
if(TARGET asan)
|
||||||
|
|
|
@ -157,6 +157,6 @@ if platform.system() == 'Darwin':
|
||||||
if apple_lldb_vers < 1000:
|
if apple_lldb_vers < 1000:
|
||||||
config.available_features.add('apple-lldb-pre-1000')
|
config.available_features.add('apple-lldb-pre-1000')
|
||||||
|
|
||||||
llvm_config.feature_config([('--build-mode', {
|
llvm_config.feature_config(
|
||||||
'Debug|RelWithDebInfo': 'debug-info'
|
[('--build-mode', {'Debug|RelWithDebInfo': 'debug-info'})]
|
||||||
})])
|
)
|
||||||
|
|
|
@ -20,6 +20,8 @@ config.target_triple = "@TARGET_TRIPLE@"
|
||||||
config.host_arch = "@HOST_ARCH@"
|
config.host_arch = "@HOST_ARCH@"
|
||||||
config.is_msvc = lit.util.pythonize_bool("@MSVC@")
|
config.is_msvc = lit.util.pythonize_bool("@MSVC@")
|
||||||
|
|
||||||
|
config.mlir_src_root = "@MLIR_SOURCE_DIR@"
|
||||||
|
|
||||||
config.llvm_use_sanitizer = "@LLVM_USE_SANITIZER@"
|
config.llvm_use_sanitizer = "@LLVM_USE_SANITIZER@"
|
||||||
|
|
||||||
config.python3_executable = "@Python3_EXECUTABLE@"
|
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:
|
if 'native' not in config.available_features or lit.util.which('gdb') is None:
|
||||||
config.unsupported = True
|
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']
|
config.suffixes = ['.gdb']
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -53,8 +53,13 @@ auto SimpleIlist = []() {
|
||||||
return Result;
|
return Result;
|
||||||
}();
|
}();
|
||||||
|
|
||||||
// Check expected instances to avoid compile errors.
|
int main() {
|
||||||
auto CheckExpectedValue = static_cast<bool>(ExpectedValue);
|
// Reference symbols that might otherwise be stripped.
|
||||||
auto CheckExpectedError = static_cast<bool>(ExpectedError);
|
ArrayRef[0];
|
||||||
|
MutableArrayRef[0];
|
||||||
int main() { return 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