r372903 - [Mangle] Add flag to asm labels to disable '\01' prefixing

via cfe-commits cfe-commits at lists.llvm.org
Wed Sep 25 15:38:24 PDT 2019


Thank you, sorry for the trouble.

vedant

> On Sep 25, 2019, at 3:36 PM, Evgenii Stepanov <eugeni.stepanov at gmail.com> wrote:
> 
> FYI I've fixed a memory leak in the new test in r372925.
> 
> On Wed, Sep 25, 2019 at 10:58 AM Vedant Kumar via cfe-commits
> <cfe-commits at lists.llvm.org> wrote:
>> 
>> Author: vedantk
>> Date: Wed Sep 25 11:00:31 2019
>> New Revision: 372903
>> 
>> URL: http://llvm.org/viewvc/llvm-project?rev=372903&view=rev
>> Log:
>> [Mangle] Add flag to asm labels to disable '\01' prefixing
>> 
>> LLDB synthesizes decls using asm labels. These decls cannot have a mangle
>> different than the one specified in the label name. I.e., the '\01' prefix
>> should not be added.
>> 
>> Fixes an expression evaluation failure in lldb's TestVirtual.py on iOS.
>> 
>> rdar://45827323
>> 
>> Differential Revision: https://reviews.llvm.org/D67774
>> 
>> Modified:
>>    cfe/trunk/include/clang/Basic/Attr.td
>>    cfe/trunk/include/clang/Basic/AttrDocs.td
>>    cfe/trunk/lib/AST/Mangle.cpp
>>    cfe/trunk/lib/Sema/SemaDecl.cpp
>>    cfe/trunk/unittests/AST/DeclTest.cpp
>> 
>> Modified: cfe/trunk/include/clang/Basic/Attr.td
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=372903&r1=372902&r2=372903&view=diff
>> ==============================================================================
>> --- cfe/trunk/include/clang/Basic/Attr.td (original)
>> +++ cfe/trunk/include/clang/Basic/Attr.td Wed Sep 25 11:00:31 2019
>> @@ -722,9 +722,25 @@ def AVRSignal : InheritableAttr, TargetS
>> 
>> def AsmLabel : InheritableAttr {
>>   let Spellings = [Keyword<"asm">, Keyword<"__asm__">];
>> -  let Args = [StringArgument<"Label">];
>> +  let Args = [
>> +    // Label specifies the mangled name for the decl.
>> +    StringArgument<"Label">,
>> +
>> +    // IsLiteralLabel specifies whether the label is literal (i.e. suppresses
>> +    // the global C symbol prefix) or not. If not, the mangle-suppression prefix
>> +    // ('\01') is omitted from the decl name at the LLVM IR level.
>> +    //
>> +    // Non-literal labels are used by some external AST sources like LLDB.
>> +    BoolArgument<"IsLiteralLabel", /*optional=*/0, /*fake=*/1>
>> +  ];
>>   let SemaHandler = 0;
>> -  let Documentation = [Undocumented];
>> +  let Documentation = [AsmLabelDocs];
>> +  let AdditionalMembers =
>> +[{
>> +bool isEquivalent(AsmLabelAttr *Other) const {
>> +  return getLabel() == Other->getLabel() && getIsLiteralLabel() == Other->getIsLiteralLabel();
>> +}
>> +}];
>> }
>> 
>> def Availability : InheritableAttr {
>> 
>> Modified: cfe/trunk/include/clang/Basic/AttrDocs.td
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/AttrDocs.td?rev=372903&r1=372902&r2=372903&view=diff
>> ==============================================================================
>> --- cfe/trunk/include/clang/Basic/AttrDocs.td (original)
>> +++ cfe/trunk/include/clang/Basic/AttrDocs.td Wed Sep 25 11:00:31 2019
>> @@ -2558,6 +2558,30 @@ manipulating bits of the enumerator when
>>   }];
>> }
>> 
>> +def AsmLabelDocs : Documentation {
>> +  let Category = DocCatDecl;
>> +  let Content = [{
>> +This attribute can be used on a function or variable to specify its symbol name.
>> +
>> +On some targets, all C symbols are prefixed by default with a single character, typically ``_``.  This was done historically to distinguish them from symbols used by other languages.  (This prefix is also added to the standard Itanium C++ ABI prefix on "mangled" symbol names, so that e.g. on such targets the true symbol name for a C++ variable declared as ``int cppvar;`` would be ``__Z6cppvar``; note the two underscores.)  This prefix is *not* added to the symbol names specified by the ``asm`` attribute; programmers wishing to match a C symbol name must compensate for this.
>> +
>> +For example, consider the following C code:
>> +
>> +.. code-block:: c
>> +
>> +  int var1 asm("altvar") = 1;  // "altvar" in symbol table.
>> +  int var2 = 1; // "_var2" in symbol table.
>> +
>> +  void func1(void) asm("altfunc");
>> +  void func1(void) {} // "altfunc" in symbol table.
>> +  void func2(void) {} // "_func2" in symbol table.
>> +
>> +Clang's implementation of this attribute is compatible with GCC's, `documented here <https://gcc.gnu.org/onlinedocs/gcc/Asm-Labels.html>`_.
>> +
>> +While it is possible to use this attribute to name a special symbol used internally by the compiler, such as an LLVM intrinsic, this is neither recommended nor supported and may cause the compiler to crash or miscompile.  Users who wish to gain access to intrinsic behavior are strongly encouraged to request new builtin functions.
>> +  }];
>> +}
>> +
>> def EnumExtensibilityDocs : Documentation {
>>   let Category = DocCatDecl;
>>   let Content = [{
>> 
>> Modified: cfe/trunk/lib/AST/Mangle.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Mangle.cpp?rev=372903&r1=372902&r2=372903&view=diff
>> ==============================================================================
>> --- cfe/trunk/lib/AST/Mangle.cpp (original)
>> +++ cfe/trunk/lib/AST/Mangle.cpp Wed Sep 25 11:00:31 2019
>> @@ -122,15 +122,21 @@ void MangleContext::mangleName(const Nam
>>   if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>()) {
>>     // If we have an asm name, then we use it as the mangling.
>> 
>> +    // If the label isn't literal, or if this is an alias for an LLVM intrinsic,
>> +    // do not add a "\01" prefix.
>> +    if (!ALA->getIsLiteralLabel() || ALA->getLabel().startswith("llvm.")) {
>> +      Out << ALA->getLabel();
>> +      return;
>> +    }
>> +
>>     // Adding the prefix can cause problems when one file has a "foo" and
>>     // another has a "\01foo". That is known to happen on ELF with the
>>     // tricks normally used for producing aliases (PR9177). Fortunately the
>>     // llvm mangler on ELF is a nop, so we can just avoid adding the \01
>> -    // marker.  We also avoid adding the marker if this is an alias for an
>> -    // LLVM intrinsic.
>> +    // marker.
>>     char GlobalPrefix =
>>         getASTContext().getTargetInfo().getDataLayout().getGlobalPrefix();
>> -    if (GlobalPrefix && !ALA->getLabel().startswith("llvm."))
>> +    if (GlobalPrefix)
>>       Out << '\01'; // LLVM IR Marker for __asm("foo")
>> 
>>     Out << ALA->getLabel();
>> 
>> Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=372903&r1=372902&r2=372903&view=diff
>> ==============================================================================
>> --- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
>> +++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Sep 25 11:00:31 2019
>> @@ -2766,7 +2766,7 @@ void Sema::mergeDeclAttributes(NamedDecl
>> 
>>   if (AsmLabelAttr *NewA = New->getAttr<AsmLabelAttr>()) {
>>     if (AsmLabelAttr *OldA = Old->getAttr<AsmLabelAttr>()) {
>> -      if (OldA->getLabel() != NewA->getLabel()) {
>> +      if (!OldA->isEquivalent(NewA)) {
>>         // This redeclaration changes __asm__ label.
>>         Diag(New->getLocation(), diag::err_different_asm_label);
>>         Diag(OldA->getLocation(), diag::note_previous_declaration);
>> @@ -6983,8 +6983,8 @@ NamedDecl *Sema::ActOnVariableDeclarator
>>       }
>>     }
>> 
>> -    NewVD->addAttr(::new (Context)
>> -                       AsmLabelAttr(Context, SE->getStrTokenLoc(0), Label));
>> +    NewVD->addAttr(::new (Context) AsmLabelAttr(
>> +        Context, SE->getStrTokenLoc(0), Label, /*IsLiteralLabel=*/true));
>>   } else if (!ExtnameUndeclaredIdentifiers.empty()) {
>>     llvm::DenseMap<IdentifierInfo*,AsmLabelAttr*>::iterator I =
>>       ExtnameUndeclaredIdentifiers.find(NewVD->getIdentifier());
>> @@ -8882,8 +8882,9 @@ Sema::ActOnFunctionDeclarator(Scope *S,
>>   if (Expr *E = (Expr*) D.getAsmLabel()) {
>>     // The parser guarantees this is a string.
>>     StringLiteral *SE = cast<StringLiteral>(E);
>> -    NewFD->addAttr(::new (Context) AsmLabelAttr(Context, SE->getStrTokenLoc(0),
>> -                                                SE->getString()));
>> +    NewFD->addAttr(::new (Context)
>> +                       AsmLabelAttr(Context, SE->getStrTokenLoc(0),
>> +                                    SE->getString(), /*IsLiteralLabel=*/true));
>>   } else if (!ExtnameUndeclaredIdentifiers.empty()) {
>>     llvm::DenseMap<IdentifierInfo*,AsmLabelAttr*>::iterator I =
>>       ExtnameUndeclaredIdentifiers.find(NewFD->getIdentifier());
>> @@ -17555,8 +17556,8 @@ void Sema::ActOnPragmaRedefineExtname(Id
>>                                          LookupOrdinaryName);
>>   AttributeCommonInfo Info(AliasName, SourceRange(AliasNameLoc),
>>                            AttributeCommonInfo::AS_Pragma);
>> -  AsmLabelAttr *Attr =
>> -      AsmLabelAttr::CreateImplicit(Context, AliasName->getName(), Info);
>> +  AsmLabelAttr *Attr = AsmLabelAttr::CreateImplicit(
>> +      Context, AliasName->getName(), /*LiteralLabel=*/true, Info);
>> 
>>   // If a declaration that:
>>   // 1) declares a function or a variable
>> 
>> Modified: cfe/trunk/unittests/AST/DeclTest.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/DeclTest.cpp?rev=372903&r1=372902&r2=372903&view=diff
>> ==============================================================================
>> --- cfe/trunk/unittests/AST/DeclTest.cpp (original)
>> +++ cfe/trunk/unittests/AST/DeclTest.cpp Wed Sep 25 11:00:31 2019
>> @@ -10,12 +10,16 @@
>> //
>> //===----------------------------------------------------------------------===//
>> 
>> +#include "clang/AST/ASTContext.h"
>> +#include "clang/AST/Mangle.h"
>> #include "clang/ASTMatchers/ASTMatchFinder.h"
>> +#include "clang/Basic/LLVM.h"
>> #include "clang/Tooling/Tooling.h"
>> #include "gtest/gtest.h"
>> 
>> using namespace clang::ast_matchers;
>> using namespace clang::tooling;
>> +using namespace clang;
>> 
>> TEST(Decl, CleansUpAPValues) {
>>   MatchFinder Finder;
>> @@ -56,3 +60,48 @@ TEST(Decl, CleansUpAPValues) {
>>       "constexpr _Complex __uint128_t c = 0xffffffffffffffff;",
>>       Args));
>> }
>> +
>> +TEST(Decl, AsmLabelAttr) {
>> +  // Create two method decls: `f` and `g`.
>> +  StringRef Code = R"(
>> +    struct S {
>> +      void f() {}
>> +      void g() {}
>> +    };
>> +  )";
>> +  auto AST =
>> +      tooling::buildASTFromCodeWithArgs(Code, {"-target", "i386-apple-darwin"});
>> +  ASTContext &Ctx = AST->getASTContext();
>> +  assert(Ctx.getTargetInfo().getDataLayout().getGlobalPrefix() &&
>> +         "Expected target to have a global prefix");
>> +  DiagnosticsEngine &Diags = AST->getDiagnostics();
>> +  SourceManager &SM = AST->getSourceManager();
>> +  FileID MainFileID = SM.getMainFileID();
>> +
>> +  // Find the method decls within the AST.
>> +  SmallVector<Decl *, 1> Decls;
>> +  AST->findFileRegionDecls(MainFileID, Code.find('{'), 0, Decls);
>> +  ASSERT_TRUE(Decls.size() == 1);
>> +  CXXRecordDecl *DeclS = cast<CXXRecordDecl>(Decls[0]);
>> +  NamedDecl *DeclF = *DeclS->method_begin();
>> +  NamedDecl *DeclG = *(++DeclS->method_begin());
>> +
>> +  // Attach asm labels to the decls: one literal, and one not.
>> +  DeclF->addAttr(::new (Ctx) AsmLabelAttr(Ctx, SourceLocation(), "foo",
>> +                                          /*LiteralLabel=*/true));
>> +  DeclG->addAttr(::new (Ctx) AsmLabelAttr(Ctx, SourceLocation(), "goo",
>> +                                          /*LiteralLabel=*/false));
>> +
>> +  // Mangle the decl names.
>> +  std::string MangleF, MangleG;
>> +  MangleContext *MC = ItaniumMangleContext::create(Ctx, Diags);
>> +  {
>> +    llvm::raw_string_ostream OS_F(MangleF);
>> +    llvm::raw_string_ostream OS_G(MangleG);
>> +    MC->mangleName(DeclF, OS_F);
>> +    MC->mangleName(DeclG, OS_G);
>> +  }
>> +
>> +  ASSERT_TRUE(0 == MangleF.compare("\x01" "foo"));
>> +  ASSERT_TRUE(0 == MangleG.compare("goo"));
>> +}
>> 
>> 
>> _______________________________________________
>> cfe-commits mailing list
>> cfe-commits at lists.llvm.org
>> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits



More information about the cfe-commits mailing list