summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaDeclAttr.cpp
diff options
context:
space:
mode:
authorYonghong Song <yhs@fb.com>2019-11-01 22:16:59 -0700
committerYonghong Song <yhs@fb.com>2019-11-09 08:17:12 -0800
commit4a5aa1a7bf8b1714b817ede8e09cd28c0784228a (patch)
tree1bc0e5f6d33732583fce0799e0ec36ac96f93621 /clang/lib/Sema/SemaDeclAttr.cpp
parent27c4eaac8c066eb1f7c5ad26c6fbc3e78eded778 (diff)
downloadbcm5719-llvm-4a5aa1a7bf8b1714b817ede8e09cd28c0784228a.tar.gz
bcm5719-llvm-4a5aa1a7bf8b1714b817ede8e09cd28c0784228a.zip
[BPF] Add preserve_access_index attribute for record definition
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
Diffstat (limited to 'clang/lib/Sema/SemaDeclAttr.cpp')
-rw-r--r--clang/lib/Sema/SemaDeclAttr.cpp66
1 files changed, 65 insertions, 1 deletions
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 7f68d201491..526e61cdf9e 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -5700,6 +5700,59 @@ static void handleAVRSignalAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
handleSimpleAttribute<AVRSignalAttr>(S, D, AL);
}
+static void handleBPFPreserveAIRecord(Sema &S, RecordDecl *RD,
+ const BPFPreserveAccessIndexAttr &AL) {
+ // Add preserve_access_index attribute to all fields and inner records.
+ for (DeclContext::decl_iterator D = RD->decls_begin(), DEnd = RD->decls_end();
+ D != DEnd; ++D) {
+ // Any member or inner struct having attribute means done.
+ if (D->hasAttr<BPFPreserveAccessIndexAttr>())
+ return;
+
+ RecordDecl *Rec = dyn_cast<RecordDecl>(*D);
+ if (Rec) {
+ Rec->addAttr(::new (S.Context) BPFPreserveAccessIndexAttr(S.Context, AL));
+ handleBPFPreserveAIRecord(S, Rec, AL);
+ } else {
+ D->addAttr(::new (S.Context) BPFPreserveAccessIndexAttr(S.Context, AL));
+ }
+ }
+}
+
+static void handleBPFPreserveAIRecord(Sema &S, RecordDecl *RD,
+ const ParsedAttr &AL) {
+ // Add preserve_access_index attribute to all fields and inner records.
+ for (DeclContext::decl_iterator D = RD->decls_begin(), DEnd = RD->decls_end();
+ D != DEnd; ++D) {
+ RecordDecl *Rec = dyn_cast<RecordDecl>(*D);
+ if (Rec) {
+ // Inner record may have been processed.
+ if (!Rec->hasAttr<BPFPreserveAccessIndexAttr>()) {
+ Rec->addAttr(::new (S.Context) BPFPreserveAccessIndexAttr(S.Context, AL));
+ handleBPFPreserveAIRecord(S, Rec, AL);
+ }
+ } else {
+ D->addAttr(::new (S.Context) BPFPreserveAccessIndexAttr(S.Context, AL));
+ }
+ }
+}
+
+static void handleBPFPreserveAccessIndexAttr(Sema &S, Decl *D,
+ const ParsedAttr &AL) {
+ RecordDecl *Rec = dyn_cast<RecordDecl>(D);
+ if (!Rec) {
+ S.Diag(D->getLocation(), diag::err_preserve_access_index_wrong_type)
+ << "preserve_addess_index" << "struct or union type";
+ return;
+ }
+
+ if (!checkAttributeNumArgs(S, AL, 0))
+ return;
+
+ handleBPFPreserveAIRecord(S, Rec, AL);
+ 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 +6629,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
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 +7381,8 @@ void Sema::ProcessDeclAttributeList(Scope *S, Decl *D,
}
}
-// 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 +7390,13 @@ void Sema::ProcessDeclAttributeDelayed(Decl *D,
handleTransparentUnionAttr(*this, D, AL);
break;
}
+
+ // For BPFPreserveAccessIndexAttr, we want to populate the attributes
+ // to fields and inner records as well.
+ if (D->hasAttr<BPFPreserveAccessIndexAttr>()) {
+ handleBPFPreserveAIRecord(*this, cast<RecordDecl>(D),
+ *D->getAttr<BPFPreserveAccessIndexAttr>());
+ }
}
// Annotation attributes are the only attributes allowed after an access
OpenPOWER on IntegriCloud