yonghong-song created this revision. yonghong-song added reviewers: ast, anakryiko. Herald added subscribers: cfe-commits, arphaman. Herald added a project: clang.
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)); 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 to that structure or union will be preserved through __builtin_preserve_{struct,union}_access_index() IR intrinsics. For bpf target, relocation will be generated. Any access beyond member access is not preserved. The following is an example to illustrate the usage: -bash-4.4$ cat t.c union s { int a; struct { int used1; int b; } __attribute__((preserve_access_index)); struct { int used2; int c; }; int d[3]; } __attribute__((preserve_access_index)); int test1(union s *arg) { return arg->a; } int test2(union s *arg) { return arg->b; } int test3(union s *arg) { return arg->c; } int test4(union s *arg) { return arg->d[1]; } int test5(union s *arg) { return __builtin_preserve_access_index(arg->d[1]); } -bash-4.4$ clang -target bpf -O2 -S -g t.c test1() generates a relocation for &s->a. test2() generates a relocation for &s->b. test3() generates a relocation for the anonymous struct which includes member "c", but no relocation is generated for anonymous structure member "c" access. test4() generates a relocation for &s->d, but no relocation is generated for array acceess with index 1. test5() generates a relocation for &s->d[1]. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D69759 Files: clang/include/clang/Basic/Attr.td clang/include/clang/Basic/AttrDocs.td clang/include/clang/Basic/DiagnosticSemaKinds.td clang/lib/CodeGen/CGExpr.cpp clang/lib/Sema/SemaDeclAttr.cpp
Index: clang/lib/Sema/SemaDeclAttr.cpp =================================================================== --- clang/lib/Sema/SemaDeclAttr.cpp +++ clang/lib/Sema/SemaDeclAttr.cpp @@ -5700,6 +5700,19 @@ handleSimpleAttribute<AVRSignalAttr>(S, D, AL); } +static void handleBPFPreserveAccessIndex(Sema &S, Decl *D, const ParsedAttr &AL) { + if (!isa<RecordDecl>(D)) { + 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; + + D->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 +6589,9 @@ case ParsedAttr::AT_AVRSignal: handleAVRSignalAttr(S, D, AL); break; + case ParsedAttr::AT_BPFPreserveAccessIndex: + handleBPFPreserveAccessIndex(S, D, AL); + break; case ParsedAttr::AT_WebAssemblyImportModule: handleWebAssemblyImportModuleAttr(S, D, AL); break; Index: clang/lib/CodeGen/CGExpr.cpp =================================================================== --- clang/lib/CodeGen/CGExpr.cpp +++ clang/lib/CodeGen/CGExpr.cpp @@ -3992,12 +3992,13 @@ const CGBitFieldInfo &Info = RL.getBitFieldInfo(field); Address Addr = base.getAddress(); unsigned Idx = RL.getLLVMFieldNo(field); - if (!IsInPreservedAIRegion) { + const RecordDecl *rec = field->getParent(); + if (!IsInPreservedAIRegion && + (!getDebugInfo() || !rec->hasAttr<BPFPreserveAccessIndexAttr>())) { if (Idx != 0) // For structs, we GEP to the field that the record layout suggests. Addr = Builder.CreateStructGEP(Addr, Idx, field->getName()); } else { - const RecordDecl *rec = field->getParent(); llvm::DIType *DbgInfo = getDebugInfo()->getOrCreateRecordType( getContext().getRecordType(rec), rec->getLocation()); Addr = Builder.CreatePreserveStructAccessIndex(Addr, Idx, @@ -4080,7 +4081,8 @@ addr = Address(Builder.CreateLaunderInvariantGroup(addr.getPointer()), addr.getAlignment()); - if (IsInPreservedAIRegion) { + if (IsInPreservedAIRegion || + (getDebugInfo() && rec->hasAttr<BPFPreserveAccessIndexAttr>())) { // Remember the original union field index llvm::DIType *DbgInfo = getDebugInfo()->getOrCreateRecordType( getContext().getRecordType(rec), rec->getLocation()); @@ -4094,7 +4096,8 @@ addr = Builder.CreateElementBitCast( addr, CGM.getTypes().ConvertTypeForMem(FieldType), field->getName()); } else { - if (!IsInPreservedAIRegion) + if (!IsInPreservedAIRegion && + (!getDebugInfo() || !rec->hasAttr<BPFPreserveAccessIndexAttr>())) // For structs, we GEP to the field that the record layout suggests. addr = emitAddrOfFieldStorage(*this, addr, field); else Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10065,6 +10065,7 @@ "__builtin_preserve_field_info argument %0 not a field access">; def err_preserve_field_info_not_const: Error< "__builtin_preserve_field_info argument %0 not a constant">; +def err_preserve_access_index_wrong_type: Error<"%0 attribute only applies to %1">; def err_bit_cast_non_trivially_copyable : Error< "__builtin_bit_cast %select{source|destination}0 type must be trivially copyable">; Index: clang/include/clang/Basic/AttrDocs.td =================================================================== --- clang/include/clang/Basic/AttrDocs.td +++ clang/include/clang/Basic/AttrDocs.td @@ -1634,6 +1634,17 @@ }]; } +def BPFPreserveAccessIndexDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +Clang supports the ``__attribute__((preserve_access_index))`` +attribute for the BPF target. This attribute may be attached to a +struct or union declaration, where if -g is specified, it enables +preserving struct or union member access debuginfo indicies of this +struct or union, similar to clang ``__builtin_preserve_acceess_index()``. + }]; +} + 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 @@ -332,6 +332,7 @@ } def TargetARM : TargetArch<["arm", "thumb", "armeb", "thumbeb"]>; def TargetAVR : TargetArch<["avr"]>; +def TargetBPF : TargetArch<["bpfel", "bpfeb"]>; def TargetMips32 : TargetArch<["mips", "mipsel"]>; def TargetAnyMips : TargetArch<["mips", "mipsel", "mips64", "mips64el"]>; def TargetMSP430 : TargetArch<["msp430"]>; @@ -1578,6 +1579,12 @@ let Subjects = SubjectList<[Function], ErrorDiag, "kernel functions">; } +def BPFPreserveAccessIndex : InheritableAttr, + TargetSpecificAttr<TargetBPF> { + let Spellings = [Clang<"preserve_access_index">]; + let Documentation = [BPFPreserveAccessIndexDocs]; +} + def WebAssemblyImportModule : InheritableAttr, TargetSpecificAttr<TargetWebAssembly> { let Spellings = [Clang<"import_module">];
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits