Skip to content

[MLIR][LLVM] Support Recursive DITypes #80251

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

Merged
merged 17 commits into from
Mar 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions mlir/include/mlir-c/Dialect/LLVM.h
Original file line number Diff line number Diff line change
Expand Up @@ -229,10 +229,10 @@ MLIR_CAPI_EXPORTED MlirAttribute mlirLLVMDIBasicTypeAttrGet(

/// Creates a LLVM DICompositeType attribute.
MLIR_CAPI_EXPORTED MlirAttribute mlirLLVMDICompositeTypeAttrGet(
MlirContext ctx, unsigned int tag, MlirAttribute name, MlirAttribute file,
uint32_t line, MlirAttribute scope, MlirAttribute baseType, int64_t flags,
uint64_t sizeInBits, uint64_t alignInBits, intptr_t nElements,
MlirAttribute const *elements);
MlirContext ctx, unsigned int tag, MlirAttribute recId, MlirAttribute name,
MlirAttribute file, uint32_t line, MlirAttribute scope,
MlirAttribute baseType, int64_t flags, uint64_t sizeInBits,
uint64_t alignInBits, intptr_t nElements, MlirAttribute const *elements);

/// Creates a LLVM DIDerivedType attribute.
MLIR_CAPI_EXPORTED MlirAttribute mlirLLVMDIDerivedTypeAttrGet(
Expand Down
2 changes: 2 additions & 0 deletions mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ add_mlir_doc(LLVMIntrinsicOps LLVMIntrinsicOps Dialects/ -gen-op-doc)
set(LLVM_TARGET_DEFINITIONS LLVMInterfaces.td)
mlir_tablegen(LLVMInterfaces.h.inc -gen-op-interface-decls)
mlir_tablegen(LLVMInterfaces.cpp.inc -gen-op-interface-defs)
mlir_tablegen(LLVMAttrInterfaces.h.inc -gen-attr-interface-decls)
mlir_tablegen(LLVMAttrInterfaces.cpp.inc -gen-attr-interface-defs)
mlir_tablegen(LLVMTypeInterfaces.h.inc -gen-type-interface-decls)
mlir_tablegen(LLVMTypeInterfaces.cpp.inc -gen-type-interface-defs)
add_public_tablegen_target(MLIRLLVMInterfacesIncGen)
Expand Down
42 changes: 31 additions & 11 deletions mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#define LLVMIR_ATTRDEFS

include "mlir/Dialect/LLVMIR/LLVMDialect.td"
include "mlir/Dialect/LLVMIR/LLVMInterfaces.td"
include "mlir/IR/AttrTypeBase.td"
include "mlir/IR/CommonAttrConstraints.td"

Expand Down Expand Up @@ -238,41 +239,43 @@ def LoopAnnotationAttr : LLVM_Attr<"LoopAnnotation", "loop_annotation"> {
//===----------------------------------------------------------------------===//

class LLVM_DIParameter<string summary, string default, string parseName,
string printName = parseName>
string errorCase, string printName = parseName>
: AttrOrTypeParameter<"unsigned", "debug info " # summary> {
let parser = [{ [&]() -> FailureOr<unsigned> {
SMLoc tagLoc = $_parser.getCurrentLocation();
StringRef name;
if ($_parser.parseKeyword(&name))
return failure();

if (unsigned tag = llvm::dwarf::get}] # parseName # [{(name))
return tag;
return $_parser.emitError(tagLoc)
<< "invalid debug info }] # summary # [{ name: " << name;
unsigned tag = llvm::dwarf::get}] # parseName # [{(name);
if (tag == }] # errorCase # [{)
return $_parser.emitError(tagLoc)
<< "invalid debug info }] # summary # [{ name: " << name;
return tag;
}() }];
let printer = "$_printer << llvm::dwarf::" # printName # "String($_self)";
let defaultValue = default;
}

def LLVM_DICallingConventionParameter : LLVM_DIParameter<
"calling convention", /*default=*/"0", "CallingConvention", "Convention"
"calling convention", /*default=*/"0", "CallingConvention", /*errorCase=*/"0",
"Convention"
>;

def LLVM_DIEncodingParameter : LLVM_DIParameter<
"encoding", /*default=*/"0", "AttributeEncoding"
"encoding", /*default=*/"0", "AttributeEncoding", /*errorCase=*/"0"
>;

def LLVM_DILanguageParameter : LLVM_DIParameter<
"language", /*default=*/"", "Language"
"language", /*default=*/"", "Language", /*errorCase=*/"0"
>;

def LLVM_DITagParameter : LLVM_DIParameter<
"tag", /*default=*/"", "Tag"
"tag", /*default=*/"", "Tag", /*errorCase=*/"llvm::dwarf::DW_TAG_invalid"
>;

def LLVM_DIOperationEncodingParameter : LLVM_DIParameter<
"operation encoding", /*default=*/"", "OperationEncoding"
"operation encoding", /*default=*/"", "OperationEncoding", /*errorCase=*/"0"
>;

//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -357,9 +360,11 @@ def LLVM_DICompileUnitAttr : LLVM_Attr<"DICompileUnit", "di_compile_unit",
//===----------------------------------------------------------------------===//

def LLVM_DICompositeTypeAttr : LLVM_Attr<"DICompositeType", "di_composite_type",
/*traits=*/[], "DITypeAttr"> {
[LLVM_DIRecursiveTypeAttrInterface],
"DITypeAttr"> {
let parameters = (ins
LLVM_DITagParameter:$tag,
OptionalParameter<"DistinctAttr">:$recId,
OptionalParameter<"StringAttr">:$name,
OptionalParameter<"DIFileAttr">:$file,
OptionalParameter<"uint32_t">:$line,
Expand All @@ -371,6 +376,21 @@ def LLVM_DICompositeTypeAttr : LLVM_Attr<"DICompositeType", "di_composite_type",
OptionalArrayRefParameter<"DINodeAttr">:$elements
);
let assemblyFormat = "`<` struct(params) `>`";
let extraClassDeclaration = [{
/// Requirements of DIRecursiveTypeAttrInterface.
/// @{

/// Get whether this attr describes a recursive self reference.
bool isRecSelf() { return getTag() == 0; }

/// Get a copy of this type attr but with the recursive ID set to `recId`.
DIRecursiveTypeAttrInterface withRecId(DistinctAttr recId);

/// Build a rec-self instance using the provided `recId`.
static DIRecursiveTypeAttrInterface getRecSelf(DistinctAttr recId);

/// @}
}];
}

//===----------------------------------------------------------------------===//
Expand Down
2 changes: 2 additions & 0 deletions mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ using linkage::Linkage;
} // namespace LLVM
} // namespace mlir

#include "mlir/Dialect/LLVMIR/LLVMAttrInterfaces.h.inc"

#define GET_ATTRDEF_CLASSES
#include "mlir/Dialect/LLVMIR/LLVMOpsAttrDefs.h.inc"

Expand Down
56 changes: 55 additions & 1 deletion mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
//
// This file defines op and type interfaces for the LLVM dialect in MLIR.
// This file defines interfaces for the LLVM dialect in MLIR.
//
//===----------------------------------------------------------------------===//

Expand Down Expand Up @@ -319,4 +319,58 @@ def LLVM_PointerElementTypeInterface
];
}

//===----------------------------------------------------------------------===//
// LLVM dialect attr interfaces.
//===----------------------------------------------------------------------===//

def LLVM_DIRecursiveTypeAttrInterface
: AttrInterface<"DIRecursiveTypeAttrInterface"> {
let description = [{
This attribute represents a DITypeAttr that is recursive. Only DITypeAttrs
that translate to LLVM DITypes that support mutation should implement this
interface.

There are two modes for conforming attributes:

1. "rec-decl":
- This attr is a recursive declaration identified by a recId.

2. "rec-self":
- This attr is considered a recursive self reference.
- This attr itself is a placeholder type that should be conceptually
replaced with the closest parent attr of the same type with the same
recId.

For example, to represent a linked list struct:

#rec_self = di_composite_type<recId = 0>
#ptr = di_derived_type<baseType: #rec_self, ...>
#field = di_derived_type<name = "next", baseType: #ptr, ...>
#rec = di_composite_type<recId = 0, name = "Node", elements: #field, ...>
#var = di_local_variable<type = #rec, ...>

Note that a rec-self without an outer rec-decl with the same recId is
conceptually the same as an "unbound" variable. The context needs to provide
meaning to the rec-self.
}];
let cppNamespace = "::mlir::LLVM";
let methods = [
InterfaceMethod<[{
Get whether this attr describes a recursive self reference.
}], "bool", "isRecSelf", (ins)>,
InterfaceMethod<[{
Get the recursive ID used for matching "rec-decl" with "rec-self".
If this attr instance is not recursive, return a null attribute.
}], "DistinctAttr", "getRecId", (ins)>,
InterfaceMethod<[{
Get a copy of this type attr but with the recursive ID set to `recId`.
}], "DIRecursiveTypeAttrInterface", "withRecId",
(ins "DistinctAttr":$recId)>,
StaticInterfaceMethod<[{
Build a rec-self instance using the provided `recId`.
}], "DIRecursiveTypeAttrInterface", "getRecSelf",
(ins "DistinctAttr":$recId)>
];
}

#endif // LLVMIR_INTERFACES
16 changes: 8 additions & 8 deletions mlir/lib/CAPI/Dialect/LLVM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,18 +152,18 @@ MlirAttribute mlirLLVMDIBasicTypeAttrGet(MlirContext ctx, unsigned int tag,
}

MlirAttribute mlirLLVMDICompositeTypeAttrGet(
MlirContext ctx, unsigned int tag, MlirAttribute name, MlirAttribute file,
uint32_t line, MlirAttribute scope, MlirAttribute baseType, int64_t flags,
uint64_t sizeInBits, uint64_t alignInBits, intptr_t nElements,
MlirAttribute const *elements) {
MlirContext ctx, unsigned int tag, MlirAttribute recId, MlirAttribute name,
MlirAttribute file, uint32_t line, MlirAttribute scope,
MlirAttribute baseType, int64_t flags, uint64_t sizeInBits,
uint64_t alignInBits, intptr_t nElements, MlirAttribute const *elements) {
SmallVector<Attribute> elementsStorage;
elementsStorage.reserve(nElements);

return wrap(DICompositeTypeAttr::get(
unwrap(ctx), tag, cast<StringAttr>(unwrap(name)),
cast<DIFileAttr>(unwrap(file)), line, cast<DIScopeAttr>(unwrap(scope)),
cast<DITypeAttr>(unwrap(baseType)), DIFlags(flags), sizeInBits,
alignInBits,
unwrap(ctx), tag, cast<DistinctAttr>(unwrap(recId)),
cast<StringAttr>(unwrap(name)), cast<DIFileAttr>(unwrap(file)), line,
cast<DIScopeAttr>(unwrap(scope)), cast<DITypeAttr>(unwrap(baseType)),
DIFlags(flags), sizeInBits, alignInBits,
llvm::map_to_vector(unwrapList(nElements, elements, elementsStorage),
[](Attribute a) { return a.cast<DINodeAttr>(); })));
}
Expand Down
19 changes: 19 additions & 0 deletions mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ static LogicalResult parseExpressionArg(AsmParser &parser, uint64_t opcode,
static void printExpressionArg(AsmPrinter &printer, uint64_t opcode,
ArrayRef<uint64_t> args);

#include "mlir/Dialect/LLVMIR/LLVMAttrInterfaces.cpp.inc"
#include "mlir/Dialect/LLVMIR/LLVMOpsEnums.cpp.inc"
#define GET_ATTRDEF_CLASSES
#include "mlir/Dialect/LLVMIR/LLVMOpsAttrDefs.cpp.inc"
Expand Down Expand Up @@ -185,6 +186,24 @@ void printExpressionArg(AsmPrinter &printer, uint64_t opcode,
});
}

//===----------------------------------------------------------------------===//
// DICompositeTypeAttr
//===----------------------------------------------------------------------===//

DIRecursiveTypeAttrInterface
DICompositeTypeAttr::withRecId(DistinctAttr recId) {
return DICompositeTypeAttr::get(getContext(), getTag(), recId, getName(),
getFile(), getLine(), getScope(),
getBaseType(), getFlags(), getSizeInBits(),
getAlignInBits(), getElements());
}

DIRecursiveTypeAttrInterface
DICompositeTypeAttr::getRecSelf(DistinctAttr recId) {
return DICompositeTypeAttr::get(recId.getContext(), 0, recId, {}, {}, 0, {},
{}, DIFlags(), 0, 0, {});
}

//===----------------------------------------------------------------------===//
// TargetFeaturesAttr
//===----------------------------------------------------------------------===//
Expand Down
Loading