yonghong-song updated this revision to Diff 382518.
yonghong-song added a comment.
- fix various clang-format and coding style issue suggested by @aaron.ballman
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D111199/new/
https://reviews.llvm.org/D111199
Files:
clang/include/clang/Basic/Attr.td
clang/include/clang/Basic/AttrDocs.td
clang/lib/AST/TypePrinter.cpp
clang/lib/CodeGen/CGDebugInfo.cpp
clang/lib/CodeGen/CGDebugInfo.h
clang/lib/Sema/SemaType.cpp
clang/test/CodeGen/attr-btf_type_tag-func.c
clang/test/CodeGen/attr-btf_type_tag-typedef-field.c
clang/test/CodeGen/attr-btf_type_tag-var.c
clang/test/Sema/attr-btf_type_tag.c
llvm/include/llvm/IR/DIBuilder.h
llvm/lib/IR/DIBuilder.cpp
llvm/test/Bitcode/attr-btf_type_tag.ll
llvm/test/DebugInfo/attr-btf_type_tag.ll
Index: llvm/test/DebugInfo/attr-btf_type_tag.ll
===================================================================
--- /dev/null
+++ llvm/test/DebugInfo/attr-btf_type_tag.ll
@@ -0,0 +1,62 @@
+; REQUIRES: x86-registered-target
+; RUN: llc -filetype=obj -o %t %s
+; RUN: llvm-dwarfdump -debug-info %t | FileCheck %s
+; Source:
+; #define __tag1 __attribute__((btf_type_tag("tag1")))
+; #define __tag2 __attribute__((btf_type_tag("tag2")))
+;
+; int * __tag1 * __tag2 *g;
+; Compilation flag:
+; clang -target x86_64 -g -S -emit-llvm t.c
+
+@g = dso_local global i32*** null, align 8, !dbg !0
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!13, !14, !15, !16, !17}
+!llvm.ident = !{!18}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = distinct !DIGlobalVariable(name: "g", scope: !2, file: !3, line: 4, type: !5, isLocal: false, isDefinition: true)
+!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 14.0.0 (https://github.com/llvm/llvm-project.git 2c240a5eefae1a945dfd36cdaa0c677eca90dd82)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !4, splitDebugInlining: false, nameTableKind: None)
+!3 = !DIFile(filename: "t.c", directory: "/home/yhs/work/tests/llvm/btf_tag_type")
+!4 = !{!0}
+!5 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !6, size: 64, annotations: !11)
+!6 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64, annotations: !9)
+!7 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !8, size: 64)
+!8 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!9 = !{!10}
+!10 = !{!"btf_type_tag", !"tag1"}
+!11 = !{!12}
+!12 = !{!"btf_type_tag", !"tag2"}
+
+; CHECK: DW_TAG_variable
+; CHECK-NEXT: DW_AT_name ("g")
+; CHECK-NEXT: DW_AT_type (0x[[T1:[0-9]+]] "int ***")
+
+; CHECK: 0x[[T1]]: DW_TAG_pointer_type
+; CHECK-NEXT: DW_AT_type (0x[[T2:[0-9]+]] "int **")
+
+; CHECK: DW_TAG_LLVM_annotation
+; CHECK-NEXT: DW_AT_name ("btf_type_tag")
+; CHECK-NEXT: DW_AT_const_value ("tag2")
+
+; CHECK: NULL
+
+; CHECK: 0x[[T2]]: DW_TAG_pointer_type
+; CHECK-NEXT: DW_AT_type (0x[[T3:[0-9]+]] "int *")
+
+; CHECK: DW_TAG_LLVM_annotation
+; CHECK-NEXT: DW_AT_name ("btf_type_tag")
+; CHECK-NEXT: DW_AT_const_value ("tag1")
+
+; CHECK: NULL
+
+; CHECK: 0x[[T3]]: DW_TAG_pointer_type
+; CHECK-NEXT: DW_AT_type (0x[[#]] "int")
+
+!13 = !{i32 7, !"Dwarf Version", i32 4}
+!14 = !{i32 2, !"Debug Info Version", i32 3}
+!15 = !{i32 1, !"wchar_size", i32 4}
+!16 = !{i32 7, !"uwtable", i32 1}
+!17 = !{i32 7, !"frame-pointer", i32 2}
+!18 = !{!"clang version 14.0.0 (https://github.com/llvm/llvm-project.git 2c240a5eefae1a945dfd36cdaa0c677eca90dd82)"}
Index: llvm/test/Bitcode/attr-btf_type_tag.ll
===================================================================
--- /dev/null
+++ llvm/test/Bitcode/attr-btf_type_tag.ll
@@ -0,0 +1,36 @@
+; RUN: llvm-as < %s | llvm-dis | FileCheck %s
+;
+; Source:
+; #define __tag1 __attribute__((btf_type_tag("tag1")))
+; int __tag1 *g;
+; Compilation flag:
+; clang -S -g -emit-llvm test.c
+
+@g = dso_local global i32* null, align 8, !dbg !0
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!9, !10, !11, !12, !13}
+!llvm.ident = !{!14}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = distinct !DIGlobalVariable(name: "g", scope: !2, file: !3, line: 2, type: !5, isLocal: false, isDefinition: true)
+!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 14.0.0 (https://github.com/llvm/llvm-project.git 248122328bfefe82608a2e110af3a3ff04279ddf)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !4, splitDebugInlining: false, nameTableKind: None)
+!3 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/llvm/btf_tag_type")
+!4 = !{!0}
+!5 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !6, size: 64, annotations: !7)
+!6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!7 = !{!8}
+!8 = !{!"btf_type_tag", !"tag1"}
+
+; CHECK: distinct !DIGlobalVariable(name: "g", scope: !2, file: !3, line: 2, type: !5
+; CHECK: !5 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !6, size: 64, annotations: !7)
+; CHECK-NEXT: !6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+; CHECK-NEXT: !7 = !{!8}
+; CHECK-NEXT: !8 = !{!"btf_type_tag", !"tag1"}
+
+!9 = !{i32 7, !"Dwarf Version", i32 4}
+!10 = !{i32 2, !"Debug Info Version", i32 3}
+!11 = !{i32 1, !"wchar_size", i32 4}
+!12 = !{i32 7, !"uwtable", i32 1}
+!13 = !{i32 7, !"frame-pointer", i32 2}
+!14 = !{!"clang version 14.0.0 (https://github.com/llvm/llvm-project.git 248122328bfefe82608a2e110af3a3ff04279ddf)"}
Index: llvm/lib/IR/DIBuilder.cpp
===================================================================
--- llvm/lib/IR/DIBuilder.cpp
+++ llvm/lib/IR/DIBuilder.cpp
@@ -287,17 +287,16 @@
0, 0, None, DINode::FlagZero);
}
-DIDerivedType *DIBuilder::createPointerType(
- DIType *PointeeTy,
- uint64_t SizeInBits,
- uint32_t AlignInBits,
- Optional<unsigned> DWARFAddressSpace,
- StringRef Name) {
+DIDerivedType *
+DIBuilder::createPointerType(DIType *PointeeTy, uint64_t SizeInBits,
+ uint32_t AlignInBits,
+ Optional<unsigned> DWARFAddressSpace,
+ StringRef Name, DINodeArray Annotations) {
// FIXME: Why is there a name here?
return DIDerivedType::get(VMContext, dwarf::DW_TAG_pointer_type, Name,
nullptr, 0, nullptr, PointeeTy, SizeInBits,
- AlignInBits, 0, DWARFAddressSpace,
- DINode::FlagZero);
+ AlignInBits, 0, DWARFAddressSpace, DINode::FlagZero,
+ nullptr, Annotations);
}
DIDerivedType *DIBuilder::createMemberPointerType(DIType *PointeeTy,
Index: llvm/include/llvm/IR/DIBuilder.h
===================================================================
--- llvm/include/llvm/IR/DIBuilder.h
+++ llvm/include/llvm/IR/DIBuilder.h
@@ -219,11 +219,12 @@
/// \param AlignInBits Alignment. (optional)
/// \param DWARFAddressSpace DWARF address space. (optional)
/// \param Name Pointer type name. (optional)
- DIDerivedType *createPointerType(DIType *PointeeTy, uint64_t SizeInBits,
- uint32_t AlignInBits = 0,
- Optional<unsigned> DWARFAddressSpace =
- None,
- StringRef Name = "");
+ /// \param Annotations Member annotations.
+ DIDerivedType *
+ createPointerType(DIType *PointeeTy, uint64_t SizeInBits,
+ uint32_t AlignInBits = 0,
+ Optional<unsigned> DWARFAddressSpace = None,
+ StringRef Name = "", DINodeArray Annotations = nullptr);
/// Create debugging information entry for a pointer to member.
/// \param PointeeTy Type pointed to by this pointer.
Index: clang/test/Sema/attr-btf_type_tag.c
===================================================================
--- /dev/null
+++ clang/test/Sema/attr-btf_type_tag.c
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -x c -triple x86_64-pc-linux-gnu -dwarf-version=4 -fsyntax-only -verify %s
+
+#define __tag1 __attribute__((btf_type_tag("tag1")))
+#define __tag2 __attribute__((btf_type_tag("tag2")))
+#define __tag3 __attribute__((btf_type_tag("tag3")))
+#define __tag4 __attribute__((btf_type_tag("tag4")))
+#define __tag5 __attribute__((btf_type_tag("tag5")))
+#define __tag6 __attribute__((btf_type_tag("tag6")))
+
+int __attribute__((btf_type_tag("tag1", "tag2"))) *invalid1; // expected-error {{'btf_type_tag' attribute takes one argument}}
+int __attribute__((btf_type_tag(2))) *invalid2; // expected-error {{'btf_type_tag' attribute requires a string}}
+
+int * __tag1 __tag2 * __tag3 __tag4 * __tag5 __tag6 *g;
+
+typedef void __fn_t(int);
+typedef __fn_t __tag1 __tag2 * __tag3 __tag4 *__fn2_t;
+struct t {
+ int __tag1 * __tag2 * __tag3 *a;
+ int __tag1 __tag2 __tag3 *b;
+ __fn2_t c;
+ long d;
+};
+int __tag4 * __tag5 * __tag6 *foo1(struct t __tag1 * __tag2 * __tag3 *a1) {
+ return (int __tag4 * __tag5 * __tag6 *)a1[0][0]->d;
+}
Index: clang/test/CodeGen/attr-btf_type_tag-var.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/attr-btf_type_tag-var.c
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 -triple %itanium_abi_triple -debug-info-kind=limited -S -emit-llvm -o - %s | FileCheck %s
+
+#define __tag1 __attribute__((btf_type_tag("tag1")))
+#define __tag2 __attribute__((btf_type_tag("tag2")))
+#define __tag3 __attribute__((btf_type_tag("tag3")))
+#define __tag4 __attribute__((btf_type_tag("tag4")))
+#define __tag5 __attribute__((btf_type_tag("tag5")))
+#define __tag6 __attribute__((btf_type_tag("tag6")))
+
+const int __tag1 __tag2 volatile * const __tag3 __tag4 volatile * __tag5 __tag6 const volatile * g;
+
+// CHECK: distinct !DIGlobalVariable(name: "g", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[L6:[0-9]+]]
+// CHECK: ![[L6]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L7:[0-9]+]], size: [[#]], annotations: ![[L22:[0-9]+]]
+// CHECK: ![[L7]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[L8:[0-9]+]]
+// CHECK: ![[L8]] = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: ![[L9:[0-9]+]]
+// CHECK: ![[L9]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L10:[0-9]+]], size: [[#]], annotations: ![[L19:[0-9]+]]
+// CHECK: ![[L10]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[L11:[0-9]+]]
+// CHECK: ![[L11]] = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: ![[L12:[0-9]+]]
+// CHECK: ![[L12]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L13:[0-9]+]], size: [[#]], annotations: ![[L16:[0-9]+]]
+// CHECK: ![[L13]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[L14:[0-9]+]]
+// CHECK: ![[L14]] = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: ![[L15:[0-9]+]]
+// CHECK: ![[L15]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed
+// CHECK: ![[L16]] = !{![[L17:[0-9]+]], ![[L18:[0-9]+]]}
+// CHECK: ![[L17]] = !{!"btf_type_tag", !"tag1"}
+// CHECK: ![[L18]] = !{!"btf_type_tag", !"tag2"}
+// CHECK: ![[L19]] = !{![[L20:[0-9]+]], ![[L21:[0-9]+]]}
+// CHECK: ![[L20]] = !{!"btf_type_tag", !"tag3"}
+// CHECK: ![[L21]] = !{!"btf_type_tag", !"tag4"}
+// CHECK: ![[L22]] = !{![[L23:[0-9]+]], ![[L24:[0-9]+]]}
+// CHECK: ![[L23]] = !{!"btf_type_tag", !"tag5"}
+// CHECK: ![[L24]] = !{!"btf_type_tag", !"tag6"}
Index: clang/test/CodeGen/attr-btf_type_tag-typedef-field.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/attr-btf_type_tag-typedef-field.c
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -triple %itanium_abi_triple -debug-info-kind=limited -S -emit-llvm -o - %s | FileCheck %s
+
+#define __tag1 __attribute__((btf_type_tag("tag1")))
+#define __tag2 __attribute__((btf_type_tag("tag2")))
+
+typedef void __fn_t(int);
+typedef __fn_t __tag1 __tag2 *__fn2_t;
+struct t {
+ int __tag1 * __tag2 *a;
+ __fn2_t b;
+ long c;
+};
+int *foo1(struct t *a1) {
+ return (int *)a1->c;
+}
+
+// CHECK: ![[L4:[0-9]+]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+// CHECK: distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t", file: ![[#]], line: [[#]], size: [[#]], elements: ![[L16:[0-9]+]])
+// CHECK: ![[L16]] = !{![[L17:[0-9]+]], ![[L24:[0-9]+]], ![[L31:[0-9]+]]}
+// CHECK: ![[L17]] = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[L18:[0-9]+]], size: [[#]])
+// CHECK: ![[L18]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L19:[0-9]+]], size: [[#]], annotations: ![[L22:[0-9]+]])
+// CHECK: ![[L19]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L4]], size: [[#]], annotations: ![[L20:[0-9]+]])
+// CHECK: ![[L20]] = !{![[L21:[0-9]+]]}
+// CHECK: ![[L21]] = !{!"btf_type_tag", !"tag1"}
+// CHECK: ![[L22]] = !{![[L23:[0-9]+]]}
+// CHECK: ![[L23]] = !{!"btf_type_tag", !"tag2"}
+// CHECK: ![[L24]] = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[L25:[0-9]+]]
+// CHECK: ![[L25]] = !DIDerivedType(tag: DW_TAG_typedef, name: "__fn2_t", file: ![[#]], line: [[#]], baseType: ![[L26:[0-9]+]])
+// CHECK: ![[L26]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L27:[0-9]+]], size: [[#]], annotations: ![[L30:[0-9]+]])
+// CHECK: ![[L27]] = !DIDerivedType(tag: DW_TAG_typedef, name: "__fn_t", file: ![[#]], line: [[#]], baseType: ![[L28:[0-9]+]])
+// CHECK: ![[L28]] = !DISubroutineType(types: ![[L29:[0-9]+]])
+// CHECK: ![[L29]] = !{null, ![[L4]]}
+// CHECK: ![[L30]] = !{![[L21]], ![[L23]]}
+// CHECK: ![[L31]] = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: ![[#]], file: ![[#]], line: [[#]]1, baseType: ![[L32:[0-9]+]]
+// CHECK: ![[L32]] = !DIBasicType(name: "long", size: [[#]], encoding: DW_ATE_signed)
Index: clang/test/CodeGen/attr-btf_type_tag-func.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/attr-btf_type_tag-func.c
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -triple %itanium_abi_triple -debug-info-kind=limited -S -emit-llvm -o - %s | FileCheck %s
+
+#define __tag1 __attribute__((btf_type_tag("tag1")))
+#define __tag2 __attribute__((btf_type_tag("tag2")))
+#define __tag3 __attribute__((btf_type_tag("tag3")))
+#define __tag4 __attribute__((btf_type_tag("tag4")))
+
+int __tag1 * __tag2 *foo(int __tag1 * __tag2 *arg) { return arg; }
+
+// CHECK: distinct !DISubprogram(name: "foo", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[L9:[0-9]+]]
+// CHECK: ![[L9]] = !DISubroutineType(types: ![[L10:[0-9]+]]
+// CHECK: ![[L10]] = !{![[L11:[0-9]+]], ![[L11]]}
+// CHECK: ![[L11]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L12:[0-9]+]], size: [[#]], annotations: ![[L16:[0-9]+]]
+// CHECK: ![[L12]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L13:[0-9]+]], size: [[#]], annotations: ![[L14:[0-9]+]]
+// CHECK: ![[L13]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed
+// CHECK: ![[L14]] = !{![[L15:[0-9]+]]}
+// CHECK: ![[L15]] = !{!"btf_type_tag", !"tag1"}
+// CHECK: ![[L16]] = !{![[L17:[0-9]+]]}
+// CHECK: ![[L17]] = !{!"btf_type_tag", !"tag2"}
+// CHECK: !DILocalVariable(name: "arg", arg: 1, scope: ![[#]], file: ![[#]], line: [[#]], type: ![[L11]])
Index: clang/lib/Sema/SemaType.cpp
===================================================================
--- clang/lib/Sema/SemaType.cpp
+++ clang/lib/Sema/SemaType.cpp
@@ -5900,6 +5900,9 @@
void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
Visit(TL.getUnqualifiedLoc());
}
+ // Allow to fill pointee's type locations, e.g.,
+ // int __attr * __attr * __attr *p;
+ void VisitPointerTypeLoc(PointerTypeLoc TL) { Visit(TL.getNextTypeLoc()); }
void VisitTypedefTypeLoc(TypedefTypeLoc TL) {
TL.setNameLoc(DS.getTypeSpecTypeLoc());
}
@@ -6500,6 +6503,34 @@
return BuildAddressSpaceAttr(T, ASIdx, AddrSpace, AttrLoc);
}
+static void HandleBTFTypeTagAttribute(QualType &Type, const ParsedAttr &Attr,
+ TypeProcessingState &State) {
+ Sema &S = State.getSema();
+
+ // Check the number of attribute arguments.
+ if (Attr.getNumArgs() != 1) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
+ << Attr << 1;
+ Attr.setInvalid();
+ return;
+ }
+
+ // Ensure the argument is a string.
+ auto *StrLiteral = dyn_cast<StringLiteral>(Attr.getArgAsExpr(0));
+ if (!StrLiteral) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
+ << Attr << AANT_ArgumentString;
+ Attr.setInvalid();
+ return;
+ }
+
+ ASTContext &Ctx = S.Context;
+ StringRef BTFTypeTag = StrLiteral->getString();
+ Type = State.getAttributedType(
+ ::new (Ctx) BTFTypeTagAttr(Ctx, Attr, BTFTypeTag), Type, Type);
+ return;
+}
+
/// HandleAddressSpaceTypeAttribute - Process an address_space attribute on the
/// specified type. The attribute contains 1 argument, the id of the address
/// space for the type.
@@ -8127,6 +8158,11 @@
case ParsedAttr::IgnoredAttribute:
break;
+ case ParsedAttr::AT_BTFTypeTag:
+ HandleBTFTypeTagAttribute(type, attr, state);
+ attr.setUsedAsTypeAttr();
+ break;
+
case ParsedAttr::AT_MayAlias:
// FIXME: This attribute needs to actually be handled, but if we ignore
// it it breaks large amounts of Linux software.
Index: clang/lib/CodeGen/CGDebugInfo.h
===================================================================
--- clang/lib/CodeGen/CGDebugInfo.h
+++ clang/lib/CodeGen/CGDebugInfo.h
@@ -178,16 +178,19 @@
llvm::DIType *CreateType(const ComplexType *Ty);
llvm::DIType *CreateType(const AutoType *Ty);
llvm::DIType *CreateType(const ExtIntType *Ty);
- llvm::DIType *CreateQualifiedType(QualType Ty, llvm::DIFile *Fg);
+ llvm::DIType *CreateQualifiedType(QualType Ty, llvm::DIFile *Fg,
+ TypeLoc TL = TypeLoc());
llvm::DIType *CreateQualifiedType(const FunctionProtoType *Ty,
llvm::DIFile *Fg);
llvm::DIType *CreateType(const TypedefType *Ty, llvm::DIFile *Fg);
llvm::DIType *CreateType(const TemplateSpecializationType *Ty,
llvm::DIFile *Fg);
llvm::DIType *CreateType(const ObjCObjectPointerType *Ty, llvm::DIFile *F);
- llvm::DIType *CreateType(const PointerType *Ty, llvm::DIFile *F);
+ llvm::DIType *CreateType(const PointerType *Ty, llvm::DIFile *F,
+ TypeLoc TL = TypeLoc());
llvm::DIType *CreateType(const BlockPointerType *Ty, llvm::DIFile *F);
- llvm::DIType *CreateType(const FunctionType *Ty, llvm::DIFile *F);
+ llvm::DIType *CreateType(const FunctionType *Ty, llvm::DIFile *F,
+ TypeLoc TL = TypeLoc());
/// Get structure or union type.
llvm::DIType *CreateType(const RecordType *Tyg);
llvm::DIType *CreateTypeDefinition(const RecordType *Ty);
@@ -242,7 +245,8 @@
/// \return namespace descriptor for the given namespace decl.
llvm::DINamespace *getOrCreateNamespace(const NamespaceDecl *N);
llvm::DIType *CreatePointerLikeType(llvm::dwarf::Tag Tag, const Type *Ty,
- QualType PointeeTy, llvm::DIFile *F);
+ QualType PointeeTy, llvm::DIFile *F,
+ TypeLoc TL = TypeLoc());
llvm::DIType *getOrCreateStructPtrType(StringRef Name, llvm::DIType *&Cache);
/// A helper function to create a subprogram for a single member
@@ -308,7 +312,8 @@
uint64_t offsetInBits, uint32_t AlignInBits,
llvm::DIFile *tunit, llvm::DIScope *scope,
const RecordDecl *RD = nullptr,
- llvm::DINodeArray Annotations = nullptr);
+ llvm::DINodeArray Annotations = nullptr,
+ TypeLoc TL = TypeLoc());
llvm::DIType *createFieldType(StringRef name, QualType type,
SourceLocation loc, AccessSpecifier AS,
@@ -628,7 +633,8 @@
Optional<StringRef> Source);
/// Get the type from the cache or create a new type if necessary.
- llvm::DIType *getOrCreateType(QualType Ty, llvm::DIFile *Fg);
+ llvm::DIType *getOrCreateType(QualType Ty, llvm::DIFile *Fg,
+ TypeLoc TL = TypeLoc());
/// Get a reference to a clang module. If \p CreateSkeletonCU is true,
/// this also creates a split dwarf skeleton compile unit.
@@ -643,7 +649,8 @@
llvm::DICompositeType *getOrCreateLimitedType(const RecordType *Ty);
/// Create type metadata for a source language type.
- llvm::DIType *CreateTypeNode(QualType Ty, llvm::DIFile *Fg);
+ llvm::DIType *CreateTypeNode(QualType Ty, llvm::DIFile *Fg,
+ TypeLoc TL = TypeLoc());
/// Create new member and increase Offset by FType's size.
llvm::DIType *CreateMemberType(llvm::DIFile *Unit, QualType FType,
Index: clang/lib/CodeGen/CGDebugInfo.cpp
===================================================================
--- clang/lib/CodeGen/CGDebugInfo.cpp
+++ clang/lib/CodeGen/CGDebugInfo.cpp
@@ -928,8 +928,28 @@
return (llvm::dwarf::Tag)0;
}
-llvm::DIType *CGDebugInfo::CreateQualifiedType(QualType Ty,
- llvm::DIFile *Unit) {
+// Strip MacroQualifiedTypeLoc and AttributedTypeLoc
+// as their corresponding types will be ignored
+// during code generation. Stripping them allows
+// to maintain proper TypeLoc for a given type
+// during code generation.
+static TypeLoc StripMacroAttributed(TypeLoc TL) {
+ if (TL.isNull())
+ return TL;
+
+ while (true) {
+ if (auto MTL = TL.getAs<MacroQualifiedTypeLoc>())
+ TL = MTL.getInnerLoc();
+ else if (auto ATL = TL.getAs<AttributedTypeLoc>())
+ TL = ATL.getModifiedLoc();
+ else
+ break;
+ }
+ return TL;
+}
+
+llvm::DIType *CGDebugInfo::CreateQualifiedType(QualType Ty, llvm::DIFile *Unit,
+ TypeLoc TL) {
QualifierCollector Qc;
const Type *T = Qc.strip(Ty);
@@ -943,7 +963,15 @@
return getOrCreateType(QualType(T, 0), Unit);
}
- auto *FromTy = getOrCreateType(Qc.apply(CGM.getContext(), T), Unit);
+ QualType NextTy = Qc.apply(CGM.getContext(), T);
+ TypeLoc NextTL;
+ if (NextTy.hasQualifiers())
+ NextTL = TL;
+ else if (!TL.isNull()) {
+ if (auto QTL = TL.getAs<QualifiedTypeLoc>())
+ NextTL = StripMacroAttributed(QTL.getNextTypeLoc());
+ }
+ auto *FromTy = getOrCreateType(NextTy, Unit, NextTL);
// No need to fill in the Name, Line, Size, Alignment, Offset in case of
// CVR derived types.
@@ -987,10 +1015,10 @@
Ty->getPointeeType(), Unit);
}
-llvm::DIType *CGDebugInfo::CreateType(const PointerType *Ty,
- llvm::DIFile *Unit) {
+llvm::DIType *CGDebugInfo::CreateType(const PointerType *Ty, llvm::DIFile *Unit,
+ TypeLoc TL) {
return CreatePointerLikeType(llvm::dwarf::DW_TAG_pointer_type, Ty,
- Ty->getPointeeType(), Unit);
+ Ty->getPointeeType(), Unit, TL);
}
/// \return whether a C++ mangling exists for the type defined by TD.
@@ -1131,7 +1159,8 @@
llvm::DIType *CGDebugInfo::CreatePointerLikeType(llvm::dwarf::Tag Tag,
const Type *Ty,
QualType PointeeTy,
- llvm::DIFile *Unit) {
+ llvm::DIFile *Unit,
+ TypeLoc TL) {
// Bit size, align and offset of the type.
// Size is always the size of a pointer. We can't use getTypeSize here
// because that does not return the correct value for references.
@@ -1141,13 +1170,52 @@
Optional<unsigned> DWARFAddressSpace =
CGM.getTarget().getDWARFAddressSpace(AddressSpace);
+ llvm::DINodeArray Annotations = nullptr;
+ TypeLoc NextTL;
+ if (!TL.isNull()) {
+ SmallVector<llvm::Metadata *, 4> Annots;
+ NextTL = TL.getNextTypeLoc();
+ if (!NextTL.isNull()) {
+ // Traverse all MacroQualifiedTypeLoc, QualifiedTypeLoc and
+ // AttributedTypeLoc type locations so we can collect
+ // BTFTypeTag attributes for this pointer.
+ while (true) {
+ if (auto MTL = NextTL.getAs<MacroQualifiedTypeLoc>()) {
+ NextTL = MTL.getInnerLoc();
+ } else if (auto QTL = NextTL.getAs<QualifiedTypeLoc>()) {
+ NextTL = QTL.getNextTypeLoc();
+ } else if (auto ATL = NextTL.getAs<AttributedTypeLoc>()) {
+ if (const auto *A = ATL.getAttrAs<BTFTypeTagAttr>()) {
+ StringRef BTFTypeTag = A->getBTFTypeTag();
+ if (!BTFTypeTag.empty()) {
+ llvm::Metadata *Ops[2] = {
+ llvm::MDString::get(CGM.getLLVMContext(),
+ StringRef("btf_type_tag")),
+ llvm::MDString::get(CGM.getLLVMContext(), BTFTypeTag)};
+ Annots.insert(Annots.begin(),
+ llvm::MDNode::get(CGM.getLLVMContext(), Ops));
+ }
+ }
+ NextTL = ATL.getModifiedLoc();
+ } else {
+ break;
+ }
+ }
+ }
+
+ NextTL = StripMacroAttributed(TL.getNextTypeLoc());
+ if (Annots.size() > 0)
+ Annotations = DBuilder.getOrCreateArray(Annots);
+ }
+
if (Tag == llvm::dwarf::DW_TAG_reference_type ||
Tag == llvm::dwarf::DW_TAG_rvalue_reference_type)
return DBuilder.createReferenceType(Tag, getOrCreateType(PointeeTy, Unit),
Size, Align, DWARFAddressSpace);
else
- return DBuilder.createPointerType(getOrCreateType(PointeeTy, Unit), Size,
- Align, DWARFAddressSpace);
+ return DBuilder.createPointerType(getOrCreateType(PointeeTy, Unit, NextTL),
+ Size, Align, DWARFAddressSpace,
+ StringRef(), Annotations);
}
llvm::DIType *CGDebugInfo::getOrCreateStructPtrType(StringRef Name,
@@ -1264,8 +1332,11 @@
llvm::DIType *CGDebugInfo::CreateType(const TypedefType *Ty,
llvm::DIFile *Unit) {
+ TypeLoc TL;
+ if (const TypeSourceInfo *TSI = Ty->getDecl()->getTypeSourceInfo())
+ TL = TSI->getTypeLoc();
llvm::DIType *Underlying =
- getOrCreateType(Ty->getDecl()->getUnderlyingType(), Unit);
+ getOrCreateType(Ty->getDecl()->getUnderlyingType(), Unit, TL);
if (Ty->getDecl()->hasAttr<NoDebugAttr>())
return Underlying;
@@ -1339,7 +1410,7 @@
}
llvm::DIType *CGDebugInfo::CreateType(const FunctionType *Ty,
- llvm::DIFile *Unit) {
+ llvm::DIFile *Unit, TypeLoc TL) {
const auto *FPT = dyn_cast<FunctionProtoType>(Ty);
if (FPT) {
if (llvm::DIType *QTy = CreateQualifiedType(FPT, Unit))
@@ -1351,17 +1422,41 @@
SmallVector<llvm::Metadata *, 16> EltTys;
// Add the result type at least.
- EltTys.push_back(getOrCreateType(Ty->getReturnType(), Unit));
+ TypeLoc RetTL;
+ if (!TL.isNull()) {
+ if (auto FTL = TL.getAs<FunctionTypeLoc>())
+ RetTL = FTL.getReturnLoc();
+ }
+ EltTys.push_back(getOrCreateType(Ty->getReturnType(), Unit, RetTL));
llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
// Set up remainder of arguments if there is a prototype.
// otherwise emit it as a variadic function.
- if (!FPT)
+ if (!FPT) {
EltTys.push_back(DBuilder.createUnspecifiedParameter());
- else {
+ } else {
Flags = getRefFlags(FPT);
- for (const QualType &ParamType : FPT->param_types())
- EltTys.push_back(getOrCreateType(ParamType, Unit));
+ bool DoneWithTL = false;
+ if (!TL.isNull()) {
+ if (auto FTL = TL.getAs<FunctionTypeLoc>()) {
+ DoneWithTL = true;
+ int Idx = 0;
+ for (const QualType &ParamType : FPT->param_types()) {
+ TypeLoc ParamTL;
+ if (ParmVarDecl *Param = FTL.getParam(Idx)) {
+ if (const TypeSourceInfo *TSI = Param->getTypeSourceInfo())
+ ParamTL = TSI->getTypeLoc();
+ }
+ EltTys.push_back(getOrCreateType(ParamType, Unit, ParamTL));
+ Idx++;
+ }
+ }
+ }
+
+ if (!DoneWithTL) {
+ for (const QualType &ParamType : FPT->param_types())
+ EltTys.push_back(getOrCreateType(ParamType, Unit));
+ }
if (FPT->isVariadic())
EltTys.push_back(DBuilder.createUnspecifiedParameter());
}
@@ -1432,11 +1527,13 @@
Flags, DebugType, Annotations);
}
-llvm::DIType *CGDebugInfo::createFieldType(
- StringRef name, QualType type, SourceLocation loc, AccessSpecifier AS,
- uint64_t offsetInBits, uint32_t AlignInBits, llvm::DIFile *tunit,
- llvm::DIScope *scope, const RecordDecl *RD, llvm::DINodeArray Annotations) {
- llvm::DIType *debugType = getOrCreateType(type, tunit);
+llvm::DIType *
+CGDebugInfo::createFieldType(StringRef name, QualType type, SourceLocation loc,
+ AccessSpecifier AS, uint64_t offsetInBits,
+ uint32_t AlignInBits, llvm::DIFile *tunit,
+ llvm::DIScope *scope, const RecordDecl *RD,
+ llvm::DINodeArray Annotations, TypeLoc TL) {
+ llvm::DIType *debugType = getOrCreateType(type, tunit, TL);
// Get the location for the field.
llvm::DIFile *file = getOrCreateFile(loc);
@@ -1544,9 +1641,12 @@
} else {
auto Align = getDeclAlignIfRequired(field, CGM.getContext());
llvm::DINodeArray Annotations = CollectBTFDeclTagAnnotations(field);
- FieldType =
- createFieldType(name, type, field->getLocation(), field->getAccess(),
- OffsetInBits, Align, tunit, RecordTy, RD, Annotations);
+ TypeLoc TL;
+ if (const TypeSourceInfo *TSI = field->getTypeSourceInfo())
+ TL = TSI->getTypeLoc();
+ FieldType = createFieldType(name, type, field->getLocation(),
+ field->getAccess(), OffsetInBits, Align, tunit,
+ RecordTy, RD, Annotations, TL);
}
elements.push_back(FieldType);
@@ -3304,7 +3404,8 @@
RetainedTypes.push_back(CGM.getContext().getRecordType(&D).getAsOpaquePtr());
}
-llvm::DIType *CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile *Unit) {
+llvm::DIType *CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile *Unit,
+ TypeLoc TL) {
if (Ty.isNull())
return nullptr;
@@ -3321,7 +3422,7 @@
if (auto *T = getTypeOrNull(Ty))
return T;
- llvm::DIType *Res = CreateTypeNode(Ty, Unit);
+ llvm::DIType *Res = CreateTypeNode(Ty, Unit, TL);
void *TyPtr = Ty.getAsOpaquePtr();
// And update the type cache.
@@ -3365,10 +3466,11 @@
return nullptr;
}
-llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) {
+llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit,
+ TypeLoc TL) {
// Handle qualifiers, which recursively handles what they refer to.
if (Ty.hasLocalQualifiers())
- return CreateQualifiedType(Ty, Unit);
+ return CreateQualifiedType(Ty, Unit, TL);
// Work out details of type.
switch (Ty->getTypeClass()) {
@@ -3397,7 +3499,7 @@
case Type::Complex:
return CreateType(cast<ComplexType>(Ty));
case Type::Pointer:
- return CreateType(cast<PointerType>(Ty), Unit);
+ return CreateType(cast<PointerType>(Ty), Unit, TL);
case Type::BlockPointer:
return CreateType(cast<BlockPointerType>(Ty), Unit);
case Type::Typedef:
@@ -3408,7 +3510,7 @@
return CreateEnumType(cast<EnumType>(Ty));
case Type::FunctionProto:
case Type::FunctionNoProto:
- return CreateType(cast<FunctionType>(Ty), Unit);
+ return CreateType(cast<FunctionType>(Ty), Unit, TL);
case Type::ConstantArray:
case Type::VariableArray:
case Type::IncompleteArray:
@@ -3953,7 +4055,12 @@
getDwarfCC(CC));
}
- return cast<llvm::DISubroutineType>(getOrCreateType(FnType, F));
+ TypeLoc TL;
+ if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
+ if (const TypeSourceInfo *TSI = FD->getTypeSourceInfo())
+ TL = TSI->getTypeLoc();
+ }
+ return cast<llvm::DISubroutineType>(getOrCreateType(FnType, F, TL));
}
QualType
@@ -4355,8 +4462,12 @@
uint64_t XOffset = 0;
if (VD->hasAttr<BlocksAttr>())
Ty = EmitTypeForVarWithBlocksAttr(VD, &XOffset).WrappedType;
- else
- Ty = getOrCreateType(VD->getType(), Unit);
+ else {
+ TypeLoc TL;
+ if (const TypeSourceInfo *TSI = VD->getTypeSourceInfo())
+ TL = TSI->getTypeLoc();
+ Ty = getOrCreateType(VD->getType(), Unit, TL);
+ }
// If there is no debug info for this type then do not emit debug info
// for this variable.
@@ -5080,10 +5191,14 @@
}
AppendAddressSpaceXDeref(AddressSpace, Expr);
+ TypeLoc TL;
+ if (const TypeSourceInfo *TSI = D->getTypeSourceInfo())
+ TL = TSI->getTypeLoc();
+
llvm::DINodeArray Annotations = CollectBTFDeclTagAnnotations(D);
GVE = DBuilder.createGlobalVariableExpression(
- DContext, DeclName, LinkageName, Unit, LineNo, getOrCreateType(T, Unit),
- Var->hasLocalLinkage(), true,
+ DContext, DeclName, LinkageName, Unit, LineNo,
+ getOrCreateType(T, Unit, TL), Var->hasLocalLinkage(), true,
Expr.empty() ? nullptr : DBuilder.createExpression(Expr),
getOrCreateStaticDataMemberDeclarationOrNull(D), TemplateParameters,
Align, Annotations);
Index: clang/lib/AST/TypePrinter.cpp
===================================================================
--- clang/lib/AST/TypePrinter.cpp
+++ clang/lib/AST/TypePrinter.cpp
@@ -1746,6 +1746,9 @@
case attr::ArmMveStrictPolymorphism:
OS << "__clang_arm_mve_strict_polymorphism";
break;
+ case attr::BTFTypeTag:
+ OS << "btf_type_tag";
+ break;
}
OS << "))";
}
Index: clang/include/clang/Basic/AttrDocs.td
===================================================================
--- clang/include/clang/Basic/AttrDocs.td
+++ clang/include/clang/Basic/AttrDocs.td
@@ -2023,6 +2023,22 @@
}];
}
+def BTFTypeTagDocs : Documentation {
+ let Category = DocCatType;
+ let Content = [{
+Clang supports the ``__attribute__((btf_type_tag("ARGUMENT")))`` attribute for
+all targets. It only has effect when ``-g`` is specified on the command line and
+may only be specified on a pointer type.
+
+The ``ARGUMENT`` string will be preserved in IR and emitted to DWARF for the
+types used in variable declarations, function declarations, or typedef
+declarations.
+
+For BPF targets, the ``ARGUMENT`` string will also be emitted to .BTF ELF
+section.
+ }];
+}
+
def MipsInterruptDocs : Documentation {
let Category = DocCatFunction;
let Heading = "interrupt (MIPS)";
Index: clang/include/clang/Basic/Attr.td
===================================================================
--- clang/include/clang/Basic/Attr.td
+++ clang/include/clang/Basic/Attr.td
@@ -1845,6 +1845,13 @@
let LangOpts = [COnly];
}
+def BTFTypeTag : TypeAttr {
+ let Spellings = [Clang<"btf_type_tag">];
+ let Args = [StringArgument<"BTFTypeTag">];
+ let Documentation = [BTFTypeTagDocs];
+ let LangOpts = [COnly];
+}
+
def WebAssemblyExportName : InheritableAttr,
TargetSpecificAttr<TargetWebAssembly> {
let Spellings = [Clang<"export_name">];
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits