This is an archive of the discontinued LLVM Phabricator instance.

[Clang][LLVM] generate btf_tag annotations for DIComposite types
ClosedPublic

Authored by yonghong-song on Jul 22 2021, 5:20 PM.

Details

Summary

Clang patch D106614 added attribute btf_tag support. This patch
generates btf_tag annotations for DIComposite types.
A field "annotations" is introduced to DIComposite, and the
annotations are represented as an DINodeArray, similar to
DIComposite elements. The following example illustrates
how annotations are encoded in IR:

distinct !DICompositeType(..., annotations: !10)
!10 = !{!11, !12}
!11 = !{!"btf_tag", !"a"}
!12 = !{!"btf_tag", !"b"}

Each btf_tag annotation is represented as a 2D array of
meta strings. Each record may have more than one
btf_tag annotations, as in the above example.

Diff Detail

Event Timeline

yonghong-song created this revision.Jul 22 2021, 5:20 PM
yonghong-song requested review of this revision.Jul 22 2021, 5:20 PM
Herald added projects: Restricted Project, Restricted Project. · View Herald TranscriptJul 22 2021, 5:20 PM
  • add more cases in clang attr-btf_tag-dicomposite.c test.
  • fix clang-format warnings.

@dblaikie The clang attr handling patch (D106614). Could you help review this patch which handles IR/BitCode Read/Write for btf_tag attributes?
This patch contains a common function which will be used by other DItypes, so this patch needs to be reviewed first.
If anybody else should review this patch, please let me know and I am happy to add them to reviewer list.

FYI. The following patches depends on this patch:

https://reviews.llvm.org/D106616 (DIDerived type: struct/union members)
https://reviews.llvm.org/D106618 (Subprogram type)
https://reviews.llvm.org/D106619 (Global variable)
https://reviews.llvm.org/D106620 (Function parameters)
https://reviews.llvm.org/D106621 (output dwarf)

@dblaikie ping. Could you help take a look at the patch?

@dblaikie ping. Could you help take a look at the patch?

Yeah, it's on my list.

clang/lib/CodeGen/CGDebugInfo.cpp
3482–3483

Any reason this has to be done with a replace-style API, rather than constructed when the DI node is constructed in the first place?

yonghong-song added inline comments.Aug 17 2021, 4:12 PM
clang/lib/CodeGen/CGDebugInfo.cpp
3482–3483

It looks DIComposite has quite a few replace-style API, e.g.,

  void replaceElements(DINodeArray Elements) {
#ifndef NDEBUG
    for (DINode *Op : getElements())
      assert(is_contained(Elements->operands(), Op) &&
             "Lost a member during member list replacement");
#endif
    replaceOperandWith(4, Elements.get());
  }

  void replaceVTableHolder(DIType *VTableHolder) {
    replaceOperandWith(5, VTableHolder);
  }

  void replaceTemplateParams(DITemplateParameterArray TemplateParams) {
    replaceOperandWith(6, TemplateParams.get());
  }

For example, elements is used with a replace-style API. I am using replace-style API just wanting to be similar to other similar fields, e.g., elements (DINodeArra) handling.

Actually most of DI* types do not use replace-style API (see my other diffs) and in those cases, I didn't use replace-style API.

But if you think I should put the fields directly during creation for DICompositeType, I can certainly do that. Please let me know your preference.

Can these values/this attribute list vary over the course of a source file? (eg: the first use of a type might only have one of the attributes specified at that point, but then more attributes appear later - and then those attributes should be applied too?)

Perhaps a test case that demonstrates the need for the replacement-style approach would be good?

The attributes should be revolved during semantic analysis stage. So looks like replace-style attribute setting is not really needed. I will change to add attribute parameter during creation time. Thanks for suggestion.

The attributes should be revolved during semantic analysis stage. So looks like replace-style attribute setting is not really needed. I will change to add attribute parameter during creation time. Thanks for suggestion.

I think semantic analysis runs alongside code generation - eg, if you have one attribute applied to a declaration, then a function definition using that type, then another declaration of the same type, but with a different attribute, then another function definition using the type - if you build the type only once, on the first use, you might not capture all the attributes?

Anyway, yeah, if all this works out without the replacement style API, I /think/ that's probably the better call. Might be worth including a test like that to show how it's expected to be handled.

(do these attributes need to work on declared-but-not-defined types? (eg: a type declared, and then a function that takes pointer-to that type, but the type is never defined in this translation unit) If so, could you include testing. for that situation?)

The attributes should be revolved during semantic analysis stage. So looks like replace-style attribute setting is not really needed. I will change to add attribute parameter during creation time. Thanks for suggestion.

I think semantic analysis runs alongside code generation - eg, if you have one attribute applied to a declaration, then a function definition using that type, then another declaration of the same type, but with a different attribute, then another function definition using the type - if you build the type only once, on the first use, you might not capture all the attributes?

For btf_tag, only C language is supported, so duplicated function definition is not allowed. In general, btf_tag attributes will be accumulated during declaration, re-declaration and definition. And we only emit debuginfo at final definition site.

Anyway, yeah, if all this works out without the replacement style API, I /think/ that's probably the better call. Might be worth including a test like that to show how it's expected to be handled.

Okay. will change from replacement API to direct parameter API.

For testing, I already had some tests for attribute accumulation in clang/test above, e.g.,

struct __tag1 __tag2 t1;
struct t1 {
  int a;
};

 struct __tag1 t2;
 struct __tag2 t2 {
   int a;
 };

 ...

I will add a few negative test to show when the debuginfo is not generated. For example, attribute for forward declaration will result in debuginfo.

(do these attributes need to work on declared-but-not-defined types? (eg: a type declared, and then a function that takes pointer-to that type, but the type is never defined in this translation unit) If so, could you include testing. for that situation?)

No. I will add a test for this.

yonghong-song edited the summary of this revision. (Show Details)
  • do not use replacement-style API to set annotations. use creation-time parameter instead.
  • add a test case to show forward declaration doesn't generate btf_tag annotations.
dblaikie accepted this revision.Aug 19 2021, 12:40 PM

Looks alright - please commit the LLVM and Clang portions of this separately. (LLVM first, shouldn't require any changes to clang/should be standalone, then committing the clang change after that, using the new API surface area to implement the desired functionality)

This revision is now accepted and ready to land.Aug 19 2021, 12:40 PM

Looks alright - please commit the LLVM and Clang portions of this separately. (LLVM first, shouldn't require any changes to clang/should be standalone, then committing the clang change after that, using the new API surface area to implement the desired functionality)

Thanks! Will do.

This revision was landed with ongoing or failed builds.Aug 19 2021, 3:38 PM
This revision was automatically updated to reflect the committed changes.