diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td --- a/clang/include/clang/Basic/Attr.td +++ b/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 { + let Spellings = [Clang<"preserve_access_index">]; + let Documentation = [BPFPreserveAccessIndexDocs]; +} + def WebAssemblyImportModule : InheritableAttr, TargetSpecificAttr { let Spellings = [Clang<"import_module">]; diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td --- a/clang/include/clang/Basic/AttrDocs.td +++ b/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)"; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/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">; diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/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())) { 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())) { // 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())) // For structs, we GEP to the field that the record layout suggests. addr = emitAddrOfFieldStorage(*this, addr, field); else diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -5700,6 +5700,19 @@ handleSimpleAttribute(S, D, AL); } +static void handleBPFPreserveAccessIndex(Sema &S, Decl *D, const ParsedAttr &AL) { + if (!isa(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;