[BPF] Add preserve_access_index attribute for record definition
This is a resubmission for the previous reverted commit
943436040121 with the same subject. This commit fixed the
segfault issue and addressed additional review comments.
This patch introduced a new bpf specific attribute which can
be added to struct or union definition. For example,
struct s { ... } __attribute__((preserve_access_index));
union u { ... } __attribute__((preserve_access_index));
The goal is to simplify user codes for cases
where preserve access index happens for certain struct/union,
so user does not need to use clang __builtin_preserve_access_index
for every members.
The attribute has no effect if -g is not specified.
When the attribute is specified and -g is specified, any member
access defined by that structure or union, including array subscript
access and inner records, will be preserved through
__builtin_preserve_{array,struct,union}_access_index()
IR intrinsics, which will enable relocation generation
in bpf backend.
The following is an example to illustrate the usage:
-bash-4.4$ cat t.c
#define __reloc__ __attribute__((preserve_access_index))
struct s1 {
int c;
} __reloc__;
struct s2 {
union {
struct s1 b[3];
};
} __reloc__;
struct s3 {
struct s2 a;
} __reloc__;
int test(struct s3 *arg) {
return arg->a.b[2].c;
}
-bash-4.4$ clang -target bpf -g -S -O2 t.c
A relocation with access string "0:0:0:0:2:0" will be generated
representing access offset of arg->a.b[2].c.
forward declaration with attribute is also handled properly such
that the attribute is copied and populated in real record definition.
Differential Revision: https://reviews.llvm.org/D69759
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 7f68d20..df6fa3d 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -5700,6 +5700,25 @@
handleSimpleAttribute<AVRSignalAttr>(S, D, AL);
}
+static void handleBPFPreserveAIRecord(Sema &S, RecordDecl *RD) {
+ // Add preserve_access_index attribute to all fields and inner records.
+ for (auto D : RD->decls()) {
+ if (D->hasAttr<BPFPreserveAccessIndexAttr>())
+ continue;
+
+ D->addAttr(BPFPreserveAccessIndexAttr::CreateImplicit(S.Context));
+ if (auto *Rec = dyn_cast<RecordDecl>(D))
+ handleBPFPreserveAIRecord(S, Rec);
+ }
+}
+
+static void handleBPFPreserveAccessIndexAttr(Sema &S, Decl *D,
+ const ParsedAttr &AL) {
+ auto *Rec = cast<RecordDecl>(D);
+ handleBPFPreserveAIRecord(S, Rec);
+ Rec->addAttr(::new (S.Context) BPFPreserveAccessIndexAttr(S.Context, AL));
+}
+
static void handleWebAssemblyImportModuleAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (!isFunctionOrMethod(D)) {
S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
@@ -6576,6 +6595,9 @@
case ParsedAttr::AT_AVRSignal:
handleAVRSignalAttr(S, D, AL);
break;
+ case ParsedAttr::AT_BPFPreserveAccessIndex:
+ handleBPFPreserveAccessIndexAttr(S, D, AL);
+ break;
case ParsedAttr::AT_WebAssemblyImportModule:
handleWebAssemblyImportModuleAttr(S, D, AL);
break;
@@ -7325,7 +7347,8 @@
}
}
-// Helper for delayed processing TransparentUnion attribute.
+// Helper for delayed processing TransparentUnion or BPFPreserveAccessIndexAttr
+// attribute.
void Sema::ProcessDeclAttributeDelayed(Decl *D,
const ParsedAttributesView &AttrList) {
for (const ParsedAttr &AL : AttrList)
@@ -7333,6 +7356,11 @@
handleTransparentUnionAttr(*this, D, AL);
break;
}
+
+ // For BPFPreserveAccessIndexAttr, we want to populate the attributes
+ // to fields and inner records as well.
+ if (D && D->hasAttr<BPFPreserveAccessIndexAttr>())
+ handleBPFPreserveAIRecord(*this, cast<RecordDecl>(D));
}
// Annotation attributes are the only attributes allowed after an access