[PATCH] D110127: [Clang] Support typedef with btf_tag attributes
Yonghong Song via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Tue Sep 21 16:28:45 PDT 2021
yonghong-song added a comment.
In D110127#3012215 <https://reviews.llvm.org/D110127#3012215>, @aaron.ballman wrote:
>> First, to build linux kernel with btf_tag annotated user pointer, we have
>>
>> #define __user __attribute__((btf_tag("user")))
>> and the linux kernel contains code like below ([2])
>>
>> typedef __signalfn_t __user *__sighandler_t;
>> and the user attribute applies to typedef type sighandler_t.
>> So clang needs to support btf_tag attribute with typedef type
>> to avoid compilation error.
>
> I want to make sure we're clear on the semantics here. That defines `__sighandler_t` to be the type `__signalfn_t __user *`, so you expect this to annotate the type, not the declaration of the typedef. So this is about allowing `btf_tag` on types in addition to declarations?
This is a good question and below are some examples:
[$ ~/work/tests/llvm/btf_tag] cat t.c
#define __tag1 __attribute__((btf_tag("tag1")))
typedef __tag1 unsigned * __u;
__u u;
[$ ~/work/tests/llvm/btf_tag] clang -Xclang -ast-dump -c t.c
...
| -TypedefDecl 0x8279c00 <<invalid sloc>> <invalid sloc> implicit __builtin_va_list 'struct __va_list_tag [1]' |
| `-ConstantArrayType 0x8234e30 'struct __va_list_tag [1]' 1 |
| `-RecordType 0x8234c70 'struct __va_list_tag' |
| `-Record 0x8234be8 '__va_list_tag' |
| -TypedefDecl 0x8279d00 <t.c:2:1, col:27> col:27 referenced __u 'unsigned int *' |
| | -PointerType 0x8279cc0 'unsigned int *' |
| | `-BuiltinType 0x8234040 'unsigned int' |
| `-BTFTagAttr 0x8279d58 <line:1:31, col:45> "tag1" |
|
`-VarDecl 0x8279df0 <line:3:1, col:5> col:5 u '__u':'unsigned int *'
[$ ~/work/tests/llvm/btf_tag] cat t.c
#define __tag1 __attribute__((btf_tag("tag1")))
typedef unsigned __tag1 * __u;
__u u;
[$ ~/work/tests/llvm/btf_tag] clang -Xclang -ast-dump -c t.c
...
| -TypedefDecl 0x8279c00 <<invalid sloc>> <invalid sloc> implicit __builtin_va_list 'struct __va_list_tag [1]' |
| `-ConstantArrayType 0x8234e30 'struct __va_list_tag [1]' 1 |
| `-RecordType 0x8234c70 'struct __va_list_tag' |
| `-Record 0x8234be8 '__va_list_tag' |
| -TypedefDecl 0x8279d00 <t.c:2:1, col:27> col:27 referenced __u 'unsigned int *' |
| | -PointerType 0x8279cc0 'unsigned int *' |
| | `-BuiltinType 0x8234040 'unsigned int' |
| `-BTFTagAttr 0x8279d58 <line:1:31, col:45> "tag1" |
|
`-VarDecl 0x8279df0 <line:3:1, col:5> col:5 u '__u':'unsigned int *'
[$ ~/work/tests/llvm/btf_tag] cat t.c
#define __tag1 __attribute__((btf_tag("tag1")))
typedef unsigned * __tag1 __u;
__u u;
[$ ~/work/tests/llvm/btf_tag] clang -Xclang -ast-dump -c t.c
...
| -TypedefDecl 0x8279c00 <<invalid sloc>> <invalid sloc> implicit __builtin_va_list 'struct __va_list_tag [1]' |
| `-ConstantArrayType 0x8234e30 'struct __va_list_tag [1]' 1 |
| `-RecordType 0x8234c70 'struct __va_list_tag' |
| `-Record 0x8234be8 '__va_list_tag' |
| -TypedefDecl 0x8279d00 <t.c:2:1, col:27> col:27 referenced __u 'unsigned int *' |
| | -PointerType 0x8279cc0 'unsigned int *' |
| | `-BuiltinType 0x8234040 'unsigned int' |
| `-BTFTagAttr 0x8279d58 <line:1:31, col:45> "tag1" |
|
`-VarDecl 0x8279df0 <line:3:1, col:5> col:5 u '__u':'unsigned int *'
[$ ~/work/tests/llvm/btf_tag] cat t.c
#define __tag1 __attribute__((btf_tag("tag1")))
typedef unsigned * __u __tag1;
__u u;
[$ ~/work/tests/llvm/btf_tag] clang -Xclang -ast-dump -c t.c
...
| -TypedefDecl 0x8279c00 <<invalid sloc>> <invalid sloc> implicit __builtin_va_list 'struct __va_list_tag [1]' |
| `-ConstantArrayType 0x8234e30 'struct __va_list_tag [1]' 1 |
| `-RecordType 0x8234c70 'struct __va_list_tag' |
| `-Record 0x8234be8 '__va_list_tag' |
| -TypedefDecl 0x8279d00 <t.c:2:1, col:20> col:20 referenced __u 'unsigned int *' |
| | -PointerType 0x8279cc0 'unsigned int *' |
| | `-BuiltinType 0x8234040 'unsigned int' |
| `-BTFTagAttr 0x8279d58 <line:1:31, col:45> "tag1" |
|
`-VarDecl 0x8279df0 <line:3:1, col:5> col:5 u '__u':'unsigned int *'
You can see that it doesn't matter where the attribute is placed, the attribute is always attached to the typedef.
I think the reason is for declarations, we only allow the btf_tag attribute to be placed for record, field, var, func, typedef,
and "unsigned *" does not qualify, so the attribute is applied to typedef.
See below example for structure, the attribute can be applied to either structure or to typedef.
>> typedef struct { ... } target_type __btf_tag
>
> Similar here -- this applies the __btf_tag to the type, not to the declaration of the typedef, right?
In the above case, it actually applied to the typedef. See below example.
[$ ~/work/tests/llvm/btf_tag] cat t.c
#define __tag1 __attribute__((btf_tag("tag1")))
typedef __tag1 struct { int a; } __s;
__s a;
[$ ~/work/tests/llvm/btf_tag] clang -Xclang -ast-dump -c t.c
...
| -RecordDecl 0x8279cb8 <t.c:2:16, col:32> col:16 struct definition |
| `-FieldDecl 0x8279d78 <col:25, col:29> col:29 a 'int' |
| -TypedefDecl 0x8279e28 <col:1, col:34> col:34 referenced __s 'struct __s':'__s' |
| | -ElaboratedType 0x8279dd0 'struct __s' sugar |
| | `-RecordType 0x8279d40 '__s' |
| | `-Record 0x8279cb8 '' |
| `-BTFTagAttr 0x8279e80 <line:1:31, col:45> "tag1" |
|
`-VarDecl 0x8279f30 <line:3:1, col:5> col:5 a '__s':'__s'
the attribute is attached to typedef.
[$ ~/work/tests/llvm/btf_tag] cat t.c
#define __tag1 __attribute__((btf_tag("tag1")))
typedef struct __tag1 { int a; } __s;
__s a;
[$ ~/work/tests/llvm/btf_tag] clang -Xclang -ast-dump -c t.c
...
| -RecordDecl 0x8279cb8 <t.c:2:9, col:32> col:9 struct definition |
| | -BTFTagAttr 0x8279d60 <line:1:31, col:45> "tag1" |
| `-FieldDecl 0x8279de0 <line:2:25, col:29> col:29 a 'int' |
| -TypedefDecl 0x8279e88 <col:1, col:34> col:34 referenced __s 'struct __s':'__s' |
| `-ElaboratedType 0x8279e30 'struct __s' sugar |
| `-RecordType 0x8279d40 '__s' |
| `-Record 0x8279cb8 '' |
|
`-VarDecl 0x8279f30 <line:3:1, col:5> col:5 a '__s':'__s'
The attribute is attached to the structure.
[$ ~/work/tests/llvm/btf_tag] cat t.c
#define __tag1 __attribute__((btf_tag("tag1")))
typedef struct { int a; } __tag1 __s;
__s a;
[$ ~/work/tests/llvm/btf_tag] clang -Xclang -ast-dump -c t.c
...
| -RecordDecl 0x8279c58 <t.c:2:9, col:25> col:9 struct definition |
| | -BTFTagAttr 0x8279dc8 <line:1:31, col:45> "tag1" |
| `-FieldDecl 0x8279d18 <line:2:18, col:22> col:22 a 'int' |
| -TypedefDecl 0x8279e88 <col:1, col:34> col:34 referenced __s 'struct __s':'__s' |
| `-ElaboratedType 0x8279e30 'struct __s' sugar |
| `-RecordType 0x8279ce0 '__s' |
| `-Record 0x8279c58 '' |
|
`-VarDecl 0x8279f30 <line:3:1, col:5> col:5 a '__s':'__s'
the attribute is attached to the structure.
[$ ~/work/tests/llvm/btf_tag] cat t.c
#define __tag1 __attribute__((btf_tag("tag1")))
typedef struct { int a; } __s __tag1;
__s a;
[$ ~/work/tests/llvm/btf_tag] clang -Xclang -ast-dump -c t.c
...
| -RecordDecl 0x8279c58 <t.c:2:9, col:25> col:9 struct definition |
| `-FieldDecl 0x8279d18 <col:18, col:22> col:22 a 'int' |
| -TypedefDecl 0x8279e28 <col:1, col:27> col:27 referenced __s 'struct __s':'__s' |
| | -ElaboratedType 0x8279dd0 'struct __s' sugar |
| | `-RecordType 0x8279ce0 '__s' |
| | `-Record 0x8279c58 '' |
| `-BTFTagAttr 0x8279e80 <line:1:31, col:45> "tag1" |
|
`-VarDecl 0x8279f30 <line:3:1, col:5> col:5 a '__s':'__s'
The attribute is attached to typedef.
> I'm asking because this raises other questions. For example:
>
> void func(int i);
> void func(int __attribute__((btf_tag("__user"))) i);
>
> Is the second a valid redeclaration of the first? Additionally:
This should be okay as btf_tag is accumulative attribute.
> __attribute__((overloadable)) void func(int i) { puts("one"); }
> __attribute__((overloadable)) void func(int __attribute__((btf_tag("__user"))) i) { puts("two"); }
>
> Is this a valid overload set because of the type attribute? Along the same lines, does adding this attribute to the type cause any ABI differences in how the type is passed?
btf_tag is for C only so overload function case won't happen.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D110127/new/
https://reviews.llvm.org/D110127
More information about the cfe-commits
mailing list