-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[mlir] Add support for recursive elements in DICompositeTypeAttr. #74948
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,136 @@ | ||||||||||||
//===- AttrDetail.h - Details of MLIR LLVM dialect attributes --------*- C++ | ||||||||||||
//-*-===// | ||||||||||||
Comment on lines
+1
to
+2
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. :nit overflow :) |
||||||||||||
// | ||||||||||||
// 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 | ||||||||||||
// | ||||||||||||
//===----------------------------------------------------------------------===// | ||||||||||||
// | ||||||||||||
// This file contains implementation details, such as storage structures, of | ||||||||||||
// MLIR LLVM dialect attributes. | ||||||||||||
// | ||||||||||||
//===----------------------------------------------------------------------===// | ||||||||||||
#ifndef DIALECT_LLVMIR_IR_ATTRDETAIL_H | ||||||||||||
Comment on lines
+13
to
+14
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
nit: newline |
||||||||||||
#define DIALECT_LLVMIR_IR_ATTRDETAIL_H | ||||||||||||
|
||||||||||||
#include "mlir/Dialect/LLVMIR/LLVMAttrs.h" | ||||||||||||
#include "mlir/IR/Types.h" | ||||||||||||
|
||||||||||||
namespace mlir { | ||||||||||||
namespace LLVM { | ||||||||||||
namespace detail { | ||||||||||||
|
||||||||||||
//===----------------------------------------------------------------------===// | ||||||||||||
// DICompositeTypeAttrStorage | ||||||||||||
//===----------------------------------------------------------------------===// | ||||||||||||
|
||||||||||||
struct DICompositeTypeAttrStorage : public ::mlir::AttributeStorage { | ||||||||||||
using KeyTy = std::tuple<unsigned, StringAttr, DIFileAttr, uint32_t, | ||||||||||||
DIScopeAttr, DITypeAttr, DIFlags, uint64_t, uint64_t, | ||||||||||||
ArrayRef<DINodeAttr>, StringAttr>; | ||||||||||||
|
||||||||||||
DICompositeTypeAttrStorage(unsigned tag, StringAttr name, DIFileAttr file, | ||||||||||||
uint32_t line, DIScopeAttr scope, | ||||||||||||
DITypeAttr baseType, DIFlags flags, | ||||||||||||
uint64_t sizeInBits, uint64_t alignInBits, | ||||||||||||
ArrayRef<DINodeAttr> elements, | ||||||||||||
StringAttr identifier = StringAttr()) | ||||||||||||
: tag(tag), name(name), file(file), line(line), scope(scope), | ||||||||||||
baseType(baseType), flags(flags), sizeInBits(sizeInBits), | ||||||||||||
alignInBits(alignInBits), elements(elements), identifier(identifier) {} | ||||||||||||
|
||||||||||||
unsigned getTag() const { return tag; } | ||||||||||||
StringAttr getName() const { return name; } | ||||||||||||
DIFileAttr getFile() const { return file; } | ||||||||||||
uint32_t getLine() const { return line; } | ||||||||||||
DIScopeAttr getScope() const { return scope; } | ||||||||||||
DITypeAttr getBaseType() const { return baseType; } | ||||||||||||
DIFlags getFlags() const { return flags; } | ||||||||||||
uint64_t getSizeInBits() const { return sizeInBits; } | ||||||||||||
uint64_t getAlignInBits() const { return alignInBits; } | ||||||||||||
ArrayRef<DINodeAttr> getElements() const { return elements; } | ||||||||||||
StringAttr getIdentifier() const { return identifier; } | ||||||||||||
|
||||||||||||
/// Returns true if this attribute is identified. | ||||||||||||
bool isIdentified() const { | ||||||||||||
return !(!identifier); | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Wouldn't this work? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nope it should be !!identifier. It's weird, but by itself it is not evaluated as a bool There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh 🦌, maybe |
||||||||||||
} | ||||||||||||
|
||||||||||||
/// Returns the respective key for this attribute. | ||||||||||||
KeyTy getAsKey() const { | ||||||||||||
if (isIdentified()) | ||||||||||||
return KeyTy(tag, name, file, line, scope, baseType, flags, sizeInBits, | ||||||||||||
alignInBits, elements, identifier); | ||||||||||||
|
||||||||||||
return KeyTy(tag, name, file, line, scope, baseType, flags, sizeInBits, | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is the distinction here necessary? I would assume the identifier (in the future hopefully id) is probably anyways default initialized to nullptr? |
||||||||||||
alignInBits, elements, StringAttr()); | ||||||||||||
} | ||||||||||||
|
||||||||||||
/// Compares two keys. | ||||||||||||
bool operator==(const KeyTy &other) const { | ||||||||||||
if (isIdentified()) | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like you design choice of only using the distinct attribute for uniquing (when computing the has and the operation==) but returning everything with getKeyAs which is nice when walking the subelements of the attribute. Can you add some comments that explain these design choices for the next reviewer / next person modifying the code. |
||||||||||||
// Just compare against the identifier. | ||||||||||||
return identifier == std::get<10>(other); | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would probably put the ID at index 0. |
||||||||||||
|
||||||||||||
// Otherwise, compare the entire tuple. | ||||||||||||
return other == getAsKey(); | ||||||||||||
} | ||||||||||||
|
||||||||||||
/// Returns the hash value of the key. | ||||||||||||
static llvm::hash_code hashKey(const KeyTy &key) { | ||||||||||||
const auto &[tag, name, file, line, scope, baseType, flags, sizeInBits, | ||||||||||||
alignInBits, elements, identifier] = key; | ||||||||||||
|
||||||||||||
if (identifier) | ||||||||||||
// Only the identifier participates in the hash id. | ||||||||||||
return hash_value(identifier); | ||||||||||||
|
||||||||||||
// Otherwise, everything else is included in the hash. | ||||||||||||
return hash_combine(tag, name, file, line, scope, baseType, flags, | ||||||||||||
sizeInBits, alignInBits, elements); | ||||||||||||
} | ||||||||||||
|
||||||||||||
/// Constructs new storage for an attribute. | ||||||||||||
static DICompositeTypeAttrStorage * | ||||||||||||
construct(AttributeStorageAllocator &allocator, const KeyTy &key) { | ||||||||||||
auto [tag, name, file, line, scope, baseType, flags, sizeInBits, | ||||||||||||
alignInBits, elements, identifier] = key; | ||||||||||||
elements = allocator.copyInto(elements); | ||||||||||||
if (identifier) { | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is the separate handling here really necessary? I would assume if identifier is nullptr we can just pass it on to the constructor? |
||||||||||||
return new (allocator.allocate<DICompositeTypeAttrStorage>()) | ||||||||||||
DICompositeTypeAttrStorage(tag, name, file, line, scope, baseType, | ||||||||||||
flags, sizeInBits, alignInBits, elements, | ||||||||||||
identifier); | ||||||||||||
} | ||||||||||||
return new (allocator.allocate<DICompositeTypeAttrStorage>()) | ||||||||||||
DICompositeTypeAttrStorage(tag, name, file, line, scope, baseType, | ||||||||||||
flags, sizeInBits, alignInBits, elements); | ||||||||||||
} | ||||||||||||
|
||||||||||||
LogicalResult mutate(AttributeStorageAllocator &allocator, | ||||||||||||
const ArrayRef<DINodeAttr>& elements) { | ||||||||||||
// Replace the elements. | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As far as I remember, most mutable upstream attributes implement a check here to ensure the elements can only be set once (or if set repeatedly they need to be set to the same value). I think such a check would be helpful here since that is presumably an error in our case (e.g. if the import sets the elements to two different values this probably indicates a collision of different LLVM DICompositeTypes to a single attribute in MLIR). |
||||||||||||
this->elements = allocator.copyInto(elements); | ||||||||||||
return success(); | ||||||||||||
} | ||||||||||||
|
||||||||||||
private: | ||||||||||||
unsigned tag; | ||||||||||||
StringAttr name; | ||||||||||||
DIFileAttr file; | ||||||||||||
uint32_t line; | ||||||||||||
DIScopeAttr scope; | ||||||||||||
DITypeAttr baseType; | ||||||||||||
DIFlags flags; | ||||||||||||
uint64_t sizeInBits; | ||||||||||||
uint64_t alignInBits; | ||||||||||||
ArrayRef<DINodeAttr> elements; | ||||||||||||
StringAttr identifier; | ||||||||||||
}; | ||||||||||||
|
||||||||||||
} // namespace detail | ||||||||||||
} // namespace LLVM | ||||||||||||
} // namespace mlir | ||||||||||||
|
||||||||||||
#endif // DIALECT_LLVMIR_IR_ATTRDETAIL_H |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: just ArrayRef should be sufficient since it is a constant reference on its own.