[llvm] 6d3ae36 - [XCOFF][AIX] Give symbol an internal name when desired symbol name contains invalid character(s)

via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 6 08:49:47 PDT 2020


Author: jasonliu
Date: 2020-07-06T15:49:15Z
New Revision: 6d3ae365bdfc846b93d1033cfe625403a3b85ac5

URL: https://github.com/llvm/llvm-project/commit/6d3ae365bdfc846b93d1033cfe625403a3b85ac5
DIFF: https://github.com/llvm/llvm-project/commit/6d3ae365bdfc846b93d1033cfe625403a3b85ac5.diff

LOG: [XCOFF][AIX] Give symbol an internal name when desired symbol name contains invalid character(s)

Summary:

When a desired symbol name contains invalid character that the
system assembler could not process, we need to emit .rename
directive in assembly path in order for that desired symbol name
to appear in the symbol table.

Reviewed By: hubert.reinterpretcast, DiggerLin, daltenty, Xiangling_L

Differential Revision: https://reviews.llvm.org/D82481

Added: 
    llvm/test/CodeGen/PowerPC/aix-xcoff-symbol-rename.ll

Modified: 
    llvm/include/llvm/MC/MCAsmInfo.h
    llvm/include/llvm/MC/MCContext.h
    llvm/include/llvm/MC/MCSectionXCOFF.h
    llvm/include/llvm/MC/MCStreamer.h
    llvm/include/llvm/MC/MCSymbolXCOFF.h
    llvm/include/llvm/MC/MCXCOFFStreamer.h
    llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
    llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
    llvm/lib/MC/MCAsmInfoXCOFF.cpp
    llvm/lib/MC/MCAsmStreamer.cpp
    llvm/lib/MC/MCContext.cpp
    llvm/lib/MC/MCStreamer.cpp
    llvm/lib/MC/MCSymbolXCOFF.cpp
    llvm/lib/MC/XCOFFObjectWriter.cpp
    llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp
    llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
    llvm/lib/Target/PowerPC/PPCISelLowering.cpp
    llvm/test/CodeGen/PowerPC/test_func_desc.ll

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/MC/MCAsmInfo.h b/llvm/include/llvm/MC/MCAsmInfo.h
index 974155ff3319..46c5a111c891 100644
--- a/llvm/include/llvm/MC/MCAsmInfo.h
+++ b/llvm/include/llvm/MC/MCAsmInfo.h
@@ -343,10 +343,6 @@ class MCAsmInfo {
   /// protected visibility.  Defaults to MCSA_Protected
   MCSymbolAttr ProtectedVisibilityAttr = MCSA_Protected;
 
-  // This attribute is used to indicate symbols such as commons on AIX may have
-  // a storage mapping class embedded in the name.
-  bool SymbolsHaveSMC = false;
-
   //===--- Dwarf Emission Directives -----------------------------------===//
 
   /// True if target supports emission of debugging information.  Defaults to
@@ -606,8 +602,6 @@ class MCAsmInfo {
     return ProtectedVisibilityAttr;
   }
 
-  bool getSymbolsHaveSMC() const { return SymbolsHaveSMC; }
-
   bool doesSupportDebugInformation() const { return SupportsDebugInformation; }
 
   bool doesSupportExceptionHandling() const {

diff  --git a/llvm/include/llvm/MC/MCContext.h b/llvm/include/llvm/MC/MCContext.h
index 3f106c697b01..45be9bb3d225 100644
--- a/llvm/include/llvm/MC/MCContext.h
+++ b/llvm/include/llvm/MC/MCContext.h
@@ -57,6 +57,7 @@ namespace llvm {
   class MCSymbol;
   class MCSymbolELF;
   class MCSymbolWasm;
+  class MCSymbolXCOFF;
   class SMLoc;
   class SourceMgr;
 
@@ -308,6 +309,9 @@ namespace llvm {
                                        unsigned UniqueID,
                                        const MCSymbolELF *LinkedToSym);
 
+    MCSymbolXCOFF *createXCOFFSymbolImpl(const StringMapEntry<bool> *Name,
+                                         bool IsTemporary);
+
     /// Map of currently defined macros.
     StringMap<MCAsmMacro> MacroMap;
 

diff  --git a/llvm/include/llvm/MC/MCSectionXCOFF.h b/llvm/include/llvm/MC/MCSectionXCOFF.h
index f6e7b0933d11..eed6b9c2609c 100644
--- a/llvm/include/llvm/MC/MCSectionXCOFF.h
+++ b/llvm/include/llvm/MC/MCSectionXCOFF.h
@@ -36,13 +36,15 @@ class MCSectionXCOFF final : public MCSection {
   XCOFF::SymbolType Type;
   XCOFF::StorageClass StorageClass;
   MCSymbolXCOFF *const QualName;
+  StringRef SymbolTableName;
   static constexpr unsigned DefaultAlignVal = 4;
 
   MCSectionXCOFF(StringRef Name, XCOFF::StorageMappingClass SMC,
                  XCOFF::SymbolType ST, XCOFF::StorageClass SC, SectionKind K,
-                 MCSymbolXCOFF *QualName, MCSymbol *Begin)
+                 MCSymbolXCOFF *QualName, MCSymbol *Begin,
+                 StringRef SymbolTableName)
       : MCSection(SV_XCOFF, Name, K, Begin), MappingClass(SMC), Type(ST),
-        StorageClass(SC), QualName(QualName) {
+        StorageClass(SC), QualName(QualName), SymbolTableName(SymbolTableName) {
     assert((ST == XCOFF::XTY_SD || ST == XCOFF::XTY_CM || ST == XCOFF::XTY_ER) &&
            "Invalid or unhandled type for csect.");
     assert(QualName != nullptr && "QualName is needed.");
@@ -72,6 +74,7 @@ class MCSectionXCOFF final : public MCSection {
                             const MCExpr *Subsection) const override;
   bool UseCodeAlign() const override;
   bool isVirtualSection() const override;
+  StringRef getSymbolTableName() const { return SymbolTableName; }
 };
 
 } // end namespace llvm

diff  --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h
index f77ecb5af50c..d7255a22e941 100644
--- a/llvm/include/llvm/MC/MCStreamer.h
+++ b/llvm/include/llvm/MC/MCStreamer.h
@@ -574,6 +574,16 @@ class MCStreamer {
   virtual void emitXCOFFSymbolLinkageWithVisibility(MCSymbol *Symbol,
                                                     MCSymbolAttr Linkage,
                                                     MCSymbolAttr Visibility);
+
+  /// Emit a XCOFF .rename directive which creates a synonym for an illegal or
+  /// undesirable name.
+  ///
+  /// \param Name - The name used internally in the assembly for references to
+  /// the symbol.
+  /// \param Rename - The value to which the Name parameter is
+  /// changed at the end of assembly.
+  virtual void emitXCOFFRenameDirective(const MCSymbol *Name, StringRef Rename);
+
   /// Emit an ELF .size directive.
   ///
   /// This corresponds to an assembler statement such as:

diff  --git a/llvm/include/llvm/MC/MCSymbolXCOFF.h b/llvm/include/llvm/MC/MCSymbolXCOFF.h
index e5bea10fd5d5..d0379ec08b7d 100644
--- a/llvm/include/llvm/MC/MCSymbolXCOFF.h
+++ b/llvm/include/llvm/MC/MCSymbolXCOFF.h
@@ -24,6 +24,16 @@ class MCSymbolXCOFF : public MCSymbol {
 
   static bool classof(const MCSymbol *S) { return S->isXCOFF(); }
 
+  static StringRef getUnqualifiedName(StringRef Name) {
+    if (Name.back() == ']') {
+      StringRef Lhs, Rhs;
+      std::tie(Lhs, Rhs) = Name.rsplit('[');
+      assert(!Rhs.empty() && "Invalid SMC format in XCOFF symbol.");
+      return Lhs;
+    }
+    return Name;
+  }
+
   void setStorageClass(XCOFF::StorageClass SC) {
     assert((!StorageClass.hasValue() || StorageClass.getValue() == SC) &&
            "Redefining StorageClass of XCOFF MCSymbol.");
@@ -36,16 +46,7 @@ class MCSymbolXCOFF : public MCSymbol {
     return StorageClass.getValue();
   }
 
-  StringRef getUnqualifiedName() const {
-    const StringRef name = getName();
-    if (name.back() == ']') {
-      StringRef lhs, rhs;
-      std::tie(lhs, rhs) = name.rsplit('[');
-      assert(!rhs.empty() && "Invalid SMC format in XCOFF symbol.");
-      return lhs;
-    }
-    return name;
-  }
+  StringRef getUnqualifiedName() const { return getUnqualifiedName(getName()); }
 
   bool hasRepresentedCsectSet() const { return RepresentedCsect != nullptr; }
 
@@ -57,10 +58,21 @@ class MCSymbolXCOFF : public MCSymbol {
 
   XCOFF::VisibilityType getVisibilityType() const { return VisibilityType; }
 
+  bool hasRename() const { return !SymbolTableName.empty(); }
+
+  void setSymbolTableName(StringRef STN) { SymbolTableName = STN; }
+
+  StringRef getSymbolTableName() const {
+    if (hasRename())
+      return SymbolTableName;
+    return getUnqualifiedName();
+  }
+
 private:
   Optional<XCOFF::StorageClass> StorageClass;
   MCSectionXCOFF *RepresentedCsect = nullptr;
   XCOFF::VisibilityType VisibilityType = XCOFF::SYM_V_UNSPECIFIED;
+  StringRef SymbolTableName;
 };
 
 } // end namespace llvm

diff  --git a/llvm/include/llvm/MC/MCXCOFFStreamer.h b/llvm/include/llvm/MC/MCXCOFFStreamer.h
index 416a55f2c8fc..5fc2efbe5284 100644
--- a/llvm/include/llvm/MC/MCXCOFFStreamer.h
+++ b/llvm/include/llvm/MC/MCXCOFFStreamer.h
@@ -32,6 +32,11 @@ class MCXCOFFStreamer : public MCObjectStreamer {
   void emitXCOFFSymbolLinkageWithVisibility(MCSymbol *Symbol,
                                             MCSymbolAttr Linkage,
                                             MCSymbolAttr Visibility) override;
+  void emitXCOFFRenameDirective(const MCSymbol *Name,
+                                StringRef Rename) override {
+    report_fatal_error("emitXCOFFRenameDirective is not implemented yet on "
+                       "object generation path");
+  }
 };
 
 } // end namespace llvm

diff  --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 98b047d74eba..27e9ffe9ea07 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -682,8 +682,7 @@ void AsmPrinter::emitFunctionHeader() {
   if (!MAI->hasVisibilityOnlyWithLinkage())
     emitVisibility(CurrentFnSym, F.getVisibility());
 
-  if (MAI->needsFunctionDescriptors() &&
-      F.getLinkage() != GlobalValue::InternalLinkage)
+  if (MAI->needsFunctionDescriptors())
     emitLinkage(&F, CurrentFnDescSym);
 
   emitLinkage(&F, CurrentFnSym);

diff  --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
index 8d670300933f..eef5c1463fde 100644
--- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
@@ -2168,6 +2168,6 @@ MCSection *TargetLoweringObjectFileXCOFF::getSectionForFunctionDescriptor(
 MCSection *TargetLoweringObjectFileXCOFF::getSectionForTOCEntry(
     const MCSymbol *Sym) const {
   return getContext().getXCOFFSection(
-      cast<MCSymbolXCOFF>(Sym)->getUnqualifiedName(), XCOFF::XMC_TC,
+      cast<MCSymbolXCOFF>(Sym)->getSymbolTableName(), XCOFF::XMC_TC,
       XCOFF::XTY_SD, XCOFF::C_HIDEXT, SectionKind::getData());
 }

diff  --git a/llvm/lib/MC/MCAsmInfoXCOFF.cpp b/llvm/lib/MC/MCAsmInfoXCOFF.cpp
index 1531f61da95e..b5c5bb3ace8e 100644
--- a/llvm/lib/MC/MCAsmInfoXCOFF.cpp
+++ b/llvm/lib/MC/MCAsmInfoXCOFF.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/MC/MCAsmInfoXCOFF.h"
+#include "llvm/ADT/StringExtras.h"
 
 using namespace llvm;
 
@@ -32,7 +33,6 @@ MCAsmInfoXCOFF::MCAsmInfoXCOFF() {
   COMMDirectiveAlignmentIsInBytes = false;
   LCOMMDirectiveAlignmentType = LCOMM::Log2Alignment;
   HasDotTypeDotSizeDirective = false;
-  SymbolsHaveSMC = true;
   UseIntegratedAssembler = false;
   NeedsFunctionDescriptors = true;
 }
@@ -43,5 +43,8 @@ bool MCAsmInfoXCOFF::isAcceptableChar(char C) const {
   if (C == '[' || C == ']')
     return true;
 
-  return MCAsmInfo::isAcceptableChar(C);
+  // For AIX assembler, symbols may consist of numeric digits,
+  // underscores, periods, uppercase or lowercase letters, or
+  // any combination of these.
+  return isAlnum(C) || C == '_' || C == '.';
 }

diff  --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp
index 9a86895a2fe1..0747ab2372ab 100644
--- a/llvm/lib/MC/MCAsmStreamer.cpp
+++ b/llvm/lib/MC/MCAsmStreamer.cpp
@@ -28,6 +28,7 @@
 #include "llvm/MC/MCRegisterInfo.h"
 #include "llvm/MC/MCSectionMachO.h"
 #include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSymbolXCOFF.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/FormattedStream.h"
@@ -174,6 +175,8 @@ class MCAsmStreamer final : public MCStreamer {
   void emitXCOFFSymbolLinkageWithVisibility(MCSymbol *Symbol,
                                             MCSymbolAttr Linakge,
                                             MCSymbolAttr Visibility) override;
+  void emitXCOFFRenameDirective(const MCSymbol *Name,
+                                StringRef Rename) override;
 
   void emitELFSize(MCSymbol *Symbol, const MCExpr *Value) override;
   void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
@@ -797,6 +800,11 @@ void MCAsmStreamer::emitXCOFFLocalCommonSymbol(MCSymbol *LabelSym,
 
 void MCAsmStreamer::emitXCOFFSymbolLinkageWithVisibility(
     MCSymbol *Symbol, MCSymbolAttr Linkage, MCSymbolAttr Visibility) {
+  // Print symbol's rename (original name contains invalid character(s)) if
+  // there is one.
+  if (cast<MCSymbolXCOFF>(Symbol)->hasRename())
+    emitXCOFFRenameDirective(Symbol,
+                             cast<MCSymbolXCOFF>(Symbol)->getSymbolTableName());
 
   switch (Linkage) {
   case MCSA_Global:
@@ -808,6 +816,9 @@ void MCAsmStreamer::emitXCOFFSymbolLinkageWithVisibility(
   case MCSA_Extern:
     OS << "\t.extern\t";
     break;
+  case MCSA_LGlobal:
+    OS << "\t.lglobl\t";
+    break;
   default:
     report_fatal_error("unhandled linkage type");
   }
@@ -830,6 +841,22 @@ void MCAsmStreamer::emitXCOFFSymbolLinkageWithVisibility(
   EmitEOL();
 }
 
+void MCAsmStreamer::emitXCOFFRenameDirective(const MCSymbol *Name,
+                                             StringRef Rename) {
+  OS << "\t.rename\t";
+  Name->print(OS, MAI);
+  const char DQ = '"';
+  OS << ',' << DQ;
+  for (char C : Rename) {
+    // To escape a double quote character, the character should be doubled.
+    if (C == DQ)
+      OS << DQ;
+    OS << C;
+  }
+  OS << DQ;
+  EmitEOL();
+}
+
 void MCAsmStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
   assert(MAI->hasDotTypeDotSizeDirective());
   OS << "\t.size\t";
@@ -841,6 +868,12 @@ void MCAsmStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
 
 void MCAsmStreamer::emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
                                      unsigned ByteAlignment) {
+  // Print symbol's rename (original name contains invalid character(s)) if
+  // there is one.
+  MCSymbolXCOFF *XSym = dyn_cast<MCSymbolXCOFF>(Symbol);
+  if (XSym && XSym->hasRename())
+    emitXCOFFRenameDirective(XSym, XSym->getSymbolTableName());
+
   OS << "\t.comm\t";
   Symbol->print(OS, MAI);
   OS << ',' << Size;

diff  --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp
index 92d99ec577b5..a0f9212f3b14 100644
--- a/llvm/lib/MC/MCContext.cpp
+++ b/llvm/lib/MC/MCContext.cpp
@@ -182,7 +182,7 @@ MCSymbol *MCContext::createSymbolImpl(const StringMapEntry<bool> *Name,
     case MCObjectFileInfo::IsWasm:
       return new (Name, *this) MCSymbolWasm(Name, IsTemporary);
     case MCObjectFileInfo::IsXCOFF:
-      return new (Name, *this) MCSymbolXCOFF(Name, IsTemporary);
+      return createXCOFFSymbolImpl(Name, IsTemporary);
     }
   }
   return new (Name, *this) MCSymbol(MCSymbol::SymbolKindUnset, Name,
@@ -292,6 +292,61 @@ void MCContext::registerInlineAsmLabel(MCSymbol *Sym) {
   InlineAsmUsedLabelNames[Sym->getName()] = Sym;
 }
 
+MCSymbolXCOFF *
+MCContext::createXCOFFSymbolImpl(const StringMapEntry<bool> *Name,
+                                 bool IsTemporary) {
+  if (!Name)
+    return new (nullptr, *this) MCSymbolXCOFF(nullptr, IsTemporary);
+
+  StringRef OriginalName = Name->first();
+  if (OriginalName.startswith("._Renamed..") ||
+      OriginalName.startswith("_Renamed.."))
+    reportError(SMLoc(), "invalid symbol name from source");
+
+  if (MAI->isValidUnquotedName(OriginalName))
+    return new (Name, *this) MCSymbolXCOFF(Name, IsTemporary);
+
+  // Now we have a name that contains invalid character(s) for XCOFF symbol.
+  // Let's replace with something valid, but save the original name so that
+  // we could still use the original name in the symbol table.
+  SmallString<128> InvalidName(OriginalName);
+
+  // If it's an entry point symbol, we will keep the '.'
+  // in front for the convention purpose. Otherwise, add "_Renamed.."
+  // as prefix to signal this is an renamed symbol.
+  const bool IsEntryPoint = !InvalidName.empty() && InvalidName[0] == '.';
+  SmallString<128> ValidName =
+      StringRef(IsEntryPoint ? "._Renamed.." : "_Renamed..");
+
+  // Append the hex values of '_' and invalid characters with "_Renamed..";
+  // at the same time replace invalid characters with '_'.
+  for (size_t I = 0; I < InvalidName.size(); ++I) {
+    if (!MAI->isAcceptableChar(InvalidName[I]) || InvalidName[I] == '_') {
+      raw_svector_ostream(ValidName).write_hex(InvalidName[I]);
+      InvalidName[I] = '_';
+    }
+  }
+
+  // Skip entry point symbol's '.' as we already have a '.' in front of
+  // "_Renamed".
+  if (IsEntryPoint)
+    ValidName.append(InvalidName.substr(1, InvalidName.size() - 1));
+  else
+    ValidName.append(InvalidName);
+
+  auto NameEntry = UsedNames.insert(std::make_pair(ValidName, true));
+  assert((NameEntry.second || !NameEntry.first->second) &&
+         "This name is used somewhere else.");
+  // Mark the name as used for a non-section symbol.
+  NameEntry.first->second = true;
+  // Have the MCSymbol object itself refer to the copy of the string
+  // that is embedded in the UsedNames entry.
+  MCSymbolXCOFF *XSym = new (&*NameEntry.first, *this)
+      MCSymbolXCOFF(&*NameEntry.first, IsTemporary);
+  XSym->setSymbolTableName(MCSymbolXCOFF::getUnqualifiedName(OriginalName));
+  return XSym;
+}
+
 //===----------------------------------------------------------------------===//
 // Section Management
 //===----------------------------------------------------------------------===//
@@ -610,15 +665,18 @@ MCSectionXCOFF *MCContext::getXCOFFSection(StringRef Section,
 
   // Otherwise, return a new section.
   StringRef CachedName = Entry.first.SectionName;
-  MCSymbol *QualName = getOrCreateSymbol(
-      CachedName + "[" + XCOFF::getMappingClassString(SMC) + "]");
+  MCSymbolXCOFF *QualName = cast<MCSymbolXCOFF>(getOrCreateSymbol(
+      CachedName + "[" + XCOFF::getMappingClassString(SMC) + "]"));
 
   MCSymbol *Begin = nullptr;
   if (BeginSymName)
     Begin = createTempSymbol(BeginSymName, false);
 
-  MCSectionXCOFF *Result = new (XCOFFAllocator.Allocate()) MCSectionXCOFF(
-      CachedName, SMC, Type, SC, Kind, cast<MCSymbolXCOFF>(QualName), Begin);
+  // QualName->getUnqualifiedName() and CachedName are the same except when
+  // CachedName contains invalid character(s) such as '$' for an XCOFF symbol.
+  MCSectionXCOFF *Result = new (XCOFFAllocator.Allocate())
+      MCSectionXCOFF(QualName->getUnqualifiedName(), SMC, Type, SC, Kind,
+                     QualName, Begin, CachedName);
   Entry.second = Result;
 
   auto *F = new MCDataFragment();

diff  --git a/llvm/lib/MC/MCStreamer.cpp b/llvm/lib/MC/MCStreamer.cpp
index 0893835caf26..6d3a933c96a3 100644
--- a/llvm/lib/MC/MCStreamer.cpp
+++ b/llvm/lib/MC/MCStreamer.cpp
@@ -1071,6 +1071,12 @@ void MCStreamer::emitXCOFFSymbolLinkageWithVisibility(MCSymbol *Symbol,
                    "XCOFF targets");
 }
 
+void MCStreamer::emitXCOFFRenameDirective(const MCSymbol *Name,
+                                          StringRef Rename) {
+  llvm_unreachable("emitXCOFFRenameDirective is only supported on "
+                   "XCOFF targets");
+}
+
 void MCStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {}
 void MCStreamer::emitELFSymverDirective(StringRef AliasName,
                                         const MCSymbol *Aliasee) {}

diff  --git a/llvm/lib/MC/MCSymbolXCOFF.cpp b/llvm/lib/MC/MCSymbolXCOFF.cpp
index 53aec88c8978..536153e5518b 100644
--- a/llvm/lib/MC/MCSymbolXCOFF.cpp
+++ b/llvm/lib/MC/MCSymbolXCOFF.cpp
@@ -17,6 +17,9 @@ MCSectionXCOFF *MCSymbolXCOFF::getRepresentedCsect() const {
           RepresentedCsect->getCSectType() == XCOFF::XTY_ER) &&
          "Symbol does not represent a csect; MCSectionXCOFF that represents "
          "the symbol should not be (but is) set.");
+  assert(getSymbolTableName().equals(RepresentedCsect->getSymbolTableName()) &&
+         "SymbolTableNames need to be the same for this symbol and its csect "
+         "representation.");
   return RepresentedCsect;
 }
 
@@ -29,5 +32,8 @@ void MCSymbolXCOFF::setRepresentedCsect(MCSectionXCOFF *C) {
           C->getCSectType() == XCOFF::XTY_ER) &&
          "Symbol does not represent a csect; can only set a MCSectionXCOFF "
          "representation for a csect.");
+  assert(getSymbolTableName().equals(C->getSymbolTableName()) &&
+         "SymbolTableNames need to be the same for this symbol and its csect "
+         "representation.");
   RepresentedCsect = C;
 }

diff  --git a/llvm/lib/MC/XCOFFObjectWriter.cpp b/llvm/lib/MC/XCOFFObjectWriter.cpp
index 70146315e120..0dabdc9777d6 100644
--- a/llvm/lib/MC/XCOFFObjectWriter.cpp
+++ b/llvm/lib/MC/XCOFFObjectWriter.cpp
@@ -68,7 +68,7 @@ struct Symbol {
   XCOFF::StorageClass getStorageClass() const {
     return MCSym->getStorageClass();
   }
-  StringRef getName() const { return MCSym->getName(); }
+  StringRef getSymbolTableName() const { return MCSym->getSymbolTableName(); }
   Symbol(const MCSymbolXCOFF *MCSym) : MCSym(MCSym), SymbolTableIndex(-1) {}
 };
 
@@ -81,7 +81,7 @@ struct ControlSection {
 
   SmallVector<Symbol, 1> Syms;
   SmallVector<XCOFFRelocation, 1> Relocations;
-  StringRef getName() const { return MCCsect->getName(); }
+  StringRef getSymbolTableName() const { return MCCsect->getSymbolTableName(); }
   ControlSection(const MCSectionXCOFF *MCSec)
       : MCCsect(MCSec), SymbolTableIndex(-1), Address(-1), Size(0) {}
 };
@@ -334,8 +334,8 @@ void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
 
     // If the name does not fit in the storage provided in the symbol table
     // entry, add it to the string table.
-    if (nameShouldBeInStringTable(MCSec->getName()))
-      Strings.add(MCSec->getName());
+    if (nameShouldBeInStringTable(MCSec->getSymbolTableName()))
+      Strings.add(MCSec->getSymbolTableName());
 
     CsectGroup &Group = getCsectGroup(MCSec);
     Group.emplace_back(MCSec);
@@ -354,8 +354,8 @@ void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
       // Handle undefined symbol.
       UndefinedCsects.emplace_back(ContainingCsect);
       SectionMap[ContainingCsect] = &UndefinedCsects.back();
-      if (nameShouldBeInStringTable(ContainingCsect->getName()))
-        Strings.add(ContainingCsect->getName());
+      if (nameShouldBeInStringTable(ContainingCsect->getSymbolTableName()))
+        Strings.add(ContainingCsect->getSymbolTableName());
       continue;
     }
 
@@ -375,8 +375,8 @@ void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
 
     // If the name does not fit in the storage provided in the symbol table
     // entry, add it to the string table.
-    if (nameShouldBeInStringTable(XSym->getName()))
-      Strings.add(XSym->getName());
+    if (nameShouldBeInStringTable(XSym->getSymbolTableName()))
+      Strings.add(XSym->getSymbolTableName());
   }
 
   Strings.finalize();
@@ -555,7 +555,7 @@ void XCOFFObjectWriter::writeSymbolTableEntryForCsectMemberLabel(
     const Symbol &SymbolRef, const ControlSection &CSectionRef,
     int16_t SectionIndex, uint64_t SymbolOffset) {
   // Name or Zeros and string table offset
-  writeSymbolName(SymbolRef.getName());
+  writeSymbolName(SymbolRef.getSymbolTableName());
   assert(SymbolOffset <= UINT32_MAX - CSectionRef.Address &&
          "Symbol address overflows.");
   W.write<uint32_t>(CSectionRef.Address + SymbolOffset);
@@ -592,7 +592,7 @@ void XCOFFObjectWriter::writeSymbolTableEntryForControlSection(
     const ControlSection &CSectionRef, int16_t SectionIndex,
     XCOFF::StorageClass StorageClass) {
   // n_name, n_zeros, n_offset
-  writeSymbolName(CSectionRef.getName());
+  writeSymbolName(CSectionRef.getSymbolTableName());
   // n_value
   W.write<uint32_t>(CSectionRef.Address);
   // n_scnum

diff  --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp
index d492fd848c7e..3092d56da1c5 100644
--- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp
+++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp
@@ -120,14 +120,17 @@ class PPCTargetAsmStreamer : public PPCTargetStreamer {
       : PPCTargetStreamer(S), OS(OS) {}
 
   void emitTCEntry(const MCSymbol &S) override {
-    const MCAsmInfo *MAI = Streamer.getContext().getAsmInfo();
-    OS << "\t.tc ";
-    OS << (MAI->getSymbolsHaveSMC()
-               ? cast<MCSymbolXCOFF>(S).getUnqualifiedName()
-               : S.getName());
-    OS << "[TC],";
-    OS << S.getName();
-    OS << '\n';
+    if (const MCSymbolXCOFF *XSym = dyn_cast<MCSymbolXCOFF>(&S)) {
+      MCSymbolXCOFF *TCSym =
+          cast<MCSymbolXCOFF>(Streamer.getContext().getOrCreateSymbol(
+              XSym->getSymbolTableName() + "[TC]"));
+      if (TCSym->hasRename())
+        Streamer.emitXCOFFRenameDirective(TCSym, TCSym->getSymbolTableName());
+      OS << "\t.tc " << TCSym->getName() << "," << XSym->getName() << '\n';
+      return;
+    }
+
+    OS << "\t.tc " << S.getName() << "[TC]," << S.getName() << '\n';
   }
 
   void emitMachine(StringRef CPU) override {

diff  --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
index b6c3086169e9..bf5fe741bac8 100644
--- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
+++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
@@ -1608,8 +1608,10 @@ void PPCAIXAsmPrinter::emitLinkage(const GlobalValue *GV,
   case GlobalValue::PrivateLinkage:
     return;
   case GlobalValue::InternalLinkage:
-    OutStreamer->emitSymbolAttribute(GVSym, MCSA_LGlobal);
-    return;
+    assert(GV->getVisibility() == GlobalValue::DefaultVisibility &&
+           "InternalLinkage should not have other visibility setting.");
+    LinkageAttr = MCSA_LGlobal;
+    break;
   case GlobalValue::AppendingLinkage:
     llvm_unreachable("Should never emit this");
   case GlobalValue::CommonLinkage:
@@ -1621,8 +1623,7 @@ void PPCAIXAsmPrinter::emitLinkage(const GlobalValue *GV,
   MCSymbolAttr VisibilityAttr = MCSA_Invalid;
   switch (GV->getVisibility()) {
 
-    // TODO: "exported" and "internal" Visibility needs to go here.
-
+  // TODO: "exported" and "internal" Visibility needs to go here.
   case GlobalValue::DefaultVisibility:
     break;
   case GlobalValue::HiddenVisibility:

diff  --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index a31b3fef2aba..40619519664f 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -5345,7 +5345,7 @@ static SDValue transformCallee(const SDValue &Callee, SelectionDAG &DAG,
           // MCSectionXCOFF to get the correct storage mapping class.
           // In this case, XCOFF::XMC_PR.
           MCSectionXCOFF *Sec = Context.getXCOFFSection(
-              S->getName(), XCOFF::XMC_PR, XCOFF::XTY_ER, SC,
+              S->getSymbolTableName(), XCOFF::XMC_PR, XCOFF::XTY_ER, SC,
               SectionKind::getMetadata());
           S->setRepresentedCsect(Sec);
         }

diff  --git a/llvm/test/CodeGen/PowerPC/aix-xcoff-symbol-rename.ll b/llvm/test/CodeGen/PowerPC/aix-xcoff-symbol-rename.ll
new file mode 100644
index 000000000000..ee3f9da68dad
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/aix-xcoff-symbol-rename.ll
@@ -0,0 +1,161 @@
+;; This file tests how llc handles symbols containing invalid characters on an
+;; XCOFF platform.
+;; Since symbol name resolution is the same between 32-bit and 64-bit,
+;; tests for 64-bit mode are omitted.
+
+; RUN: llc -verify-machineinstrs -mtriple powerpc-ibm-aix-xcoff -mcpu=pwr4 \
+; RUN:     -mattr=-altivec < %s | \
+; RUN:   FileCheck --check-prefix=ASM %s
+
+; RUN: llc -verify-machineinstrs -mtriple powerpc-ibm-aix-xcoff -mcpu=pwr4 \
+; RUN:     -mattr=-altivec -filetype=obj -o %t.o < %s
+; RUN: llvm-objdump -D -r --symbol-description %t.o | \
+; RUN:   FileCheck --check-prefix=OBJ %s
+
+; This is f`o
+@"f\60o" = global i32 10, align 4
+
+; This is f"o"
+@"f\22o\22" = common global i32 0, align 4
+
+define internal i32 @f$o() {
+entry:
+  %call = call i32 bitcast (i32 (...)* @"f\40o" to i32 ()*)()
+  ret i32 %call
+}
+
+; This is f&o
+define i32 @"f\26o"() {
+entry:
+  %call = call i32 @f$o()
+  ret i32 %call
+}
+
+; This is f&_o
+define i32 (...)* @"f\26_o"() {
+entry:
+  ret i32 (...)* @"f\40o"
+}
+
+; This is f at o
+declare i32 @"f\40o"(...)
+
+; ASM:         .rename _Renamed..24f_o[DS],"f$o" # -- Begin function f$o
+; ASM-NEXT:    .lglobl _Renamed..24f_o[DS]
+; ASM-NEXT:    .rename ._Renamed..24f_o,".f$o"
+; ASM-NEXT:    .lglobl ._Renamed..24f_o
+; ASM-NEXT:    .align  4
+; ASM-NEXT:    .csect _Renamed..24f_o[DS],2
+; ASM-NEXT:    .vbyte  4, ._Renamed..24f_o     # @"f$o"
+; ASM-NEXT:    .vbyte  4, TOC[TC0]
+; ASM-NEXT:    .vbyte  4, 0
+; ASM-NEXT:    .csect .text[PR],2
+; ASM-NEXT:  ._Renamed..24f_o:
+; ASM:         bl ._Renamed..40f_o
+; ASM-NEXT:    nop
+; ASM:         .rename _Renamed..26f_o[DS],"f&o" # -- Begin function f&o
+; ASM-NEXT:    .globl  _Renamed..26f_o[DS]
+; ASM-NEXT:    .rename ._Renamed..26f_o,".f&o"
+; ASM-NEXT:    .globl  ._Renamed..26f_o
+; ASM-NEXT:    .align  4
+; ASM-NEXT:    .csect _Renamed..26f_o[DS],2
+; ASM-NEXT:    .vbyte  4, ._Renamed..26f_o     # @"f&o"
+; ASM-NEXT:    .vbyte  4, TOC[TC0]
+; ASM-NEXT:    .vbyte  4, 0
+; ASM-NEXT:    .csect .text[PR],2
+; ASM-NEXT:  ._Renamed..26f_o:
+; ASM:         bl ._Renamed..24f_o
+; ASM:         .rename _Renamed..265ff__o[DS],"f&_o" # -- Begin function f&_o
+; ASM-NEXT:    .globl  _Renamed..265ff__o[DS]
+; ASM-NEXT:    .rename ._Renamed..265ff__o,".f&_o"
+; ASM-NEXT:    .globl  ._Renamed..265ff__o
+; ASM-NEXT:    .align  4
+; ASM-NEXT:    .csect _Renamed..265ff__o[DS],2
+; ASM-NEXT:    .vbyte  4, ._Renamed..265ff__o  # @"f&_o"
+; ASM-NEXT:    .vbyte  4, TOC[TC0]
+; ASM-NEXT:    .vbyte  4, 0
+; ASM-NEXT:    .csect .text[PR],2
+; ASM-NEXT:  ._Renamed..265ff__o:
+; ASM:         .csect .data[RW],2
+; ASM-NEXT:    .rename _Renamed..60f_o,"f`o"
+; ASM-NEXT:    .globl  _Renamed..60f_o
+; ASM-NEXT:    .align  2
+; ASM-NEXT:  _Renamed..60f_o:
+; ASM-NEXT:    .vbyte  4, 10                   # 0xa
+; ASM-NEXT:    .rename _Renamed..2222f_o_[RW],"f""o"""
+; ASM-NEXT:    .comm _Renamed..2222f_o_[RW],4,2
+; ASM-NEXT:    .rename ._Renamed..40f_o,".f at o"
+; ASM-NEXT:    .extern ._Renamed..40f_o
+; ASM-NEXT:    .rename _Renamed..40f_o[DS],"f at o"
+; ASM-NEXT:    .extern _Renamed..40f_o[DS]
+; ASM-NEXT:    .toc
+; ASM-NEXT:  L..C0:
+; ASM-NEXT:    .rename _Renamed..40f_o[TC],"f at o"
+; ASM-NEXT:    .tc _Renamed..40f_o[TC],_Renamed..40f_o[DS]
+
+; OBJ:       Disassembly of section .text:
+; OBJ-EMPTY:
+; OBJ-NEXT:  00000000 (idx: 6) .f$o:
+; OBJ-NEXT:         0: 7c 08 02 a6   mflr 0
+; OBJ-NEXT:         4: 90 01 00 08   stw 0, 8(1)
+; OBJ-NEXT:         8: 94 21 ff c0   stwu 1, -64(1)
+; OBJ-NEXT:         c: 4b ff ff f5   bl 0x0
+; OBJ-NEXT:                          0000000c:  R_RBR        (idx: 0) .f at o[PR]
+; OBJ-NEXT:        10: 60 00 00 00   nop
+; OBJ-NEXT:        14: 38 21 00 40   addi 1, 1, 64
+; OBJ-NEXT:        18: 80 01 00 08   lwz 0, 8(1)
+; OBJ-NEXT:        1c: 7c 08 03 a6   mtlr 0
+; OBJ-NEXT:        20: 4e 80 00 20   blr
+; OBJ-NEXT:        24: 60 00 00 00   nop
+; OBJ-NEXT:        28: 60 00 00 00   nop
+; OBJ-NEXT:        2c: 60 00 00 00   nop
+; OBJ-EMPTY:
+; OBJ-NEXT:  00000030 (idx: 8) .f&o:
+; OBJ-NEXT:        30: 7c 08 02 a6   mflr 0
+; OBJ-NEXT:        34: 90 01 00 08   stw 0, 8(1)
+; OBJ-NEXT:        38: 94 21 ff c0   stwu 1, -64(1)
+; OBJ-NEXT:        3c: 4b ff ff c5   bl 0x0
+; OBJ-NEXT:        40: 38 21 00 40   addi 1, 1, 64
+; OBJ-NEXT:        44: 80 01 00 08   lwz 0, 8(1)
+; OBJ-NEXT:        48: 7c 08 03 a6   mtlr 0
+; OBJ-NEXT:        4c: 4e 80 00 20   blr
+; OBJ-EMPTY:
+; OBJ-NEXT:  00000050 (idx: 10) .f&_o:
+; OBJ-NEXT:        50: 80 62 00 00   lwz 3, 0(2)
+; OBJ-NEXT:                          00000052:  R_TOC        (idx: 24) f at o[TC]
+; OBJ-NEXT:        54: 4e 80 00 20   blr
+; OBJ-EMPTY:
+; OBJ-NEXT:  Disassembly of section .data:
+; OBJ-EMPTY:
+; OBJ-NEXT:  00000058 (idx: 14) f`o:
+; OBJ-NEXT:        58: 00 00 00 0a   <unknown>
+; OBJ-EMPTY:
+; OBJ-NEXT:  0000005c (idx: 16) f$o[DS]:
+; OBJ-NEXT:        5c: 00 00 00 00   <unknown>
+; OBJ-NEXT:                          0000005c:  R_POS        (idx: 6) .f$o
+; OBJ-NEXT:        60: 00 00 00 80   <unknown>
+; OBJ-NEXT:                          00000060:  R_POS        (idx: 22) TOC[TC0]
+; OBJ-NEXT:        64: 00 00 00 00   <unknown>
+; OBJ-EMPTY:
+; OBJ-NEXT:  00000068 (idx: 18) f&o[DS]:
+; OBJ-NEXT:        68: 00 00 00 30   <unknown>
+; OBJ-NEXT:                          00000068:  R_POS        (idx: 8) .f&o
+; OBJ-NEXT:        6c: 00 00 00 80   <unknown>
+; OBJ-NEXT:                          0000006c:  R_POS        (idx: 22) TOC[TC0]
+; OBJ-NEXT:        70: 00 00 00 00   <unknown>
+; OBJ-EMPTY:
+; OBJ-NEXT:  00000074 (idx: 20) f&_o[DS]:
+; OBJ-NEXT:        74: 00 00 00 50   <unknown>
+; OBJ-NEXT:                          00000074:  R_POS        (idx: 10) .f&_o
+; OBJ-NEXT:        78: 00 00 00 80   <unknown>
+; OBJ-NEXT:                          00000078:  R_POS        (idx: 22) TOC[TC0]
+; OBJ-NEXT:        7c: 00 00 00 00   <unknown>
+; OBJ-EMPTY:
+; OBJ-NEXT:  00000080 (idx: 24) f at o[TC]:
+; OBJ-NEXT:        80: 00 00 00 00   <unknown>
+; OBJ-NEXT:                          00000080:  R_POS        (idx: 2) f at o[DS]
+; OBJ-EMPTY:
+; OBJ-NEXT:  Disassembly of section .bss:
+; OBJ-EMPTY:
+; OBJ-NEXT:  00000084 (idx: 26) f"o"[RW]:
+; OBJ-NEXT:  ...

diff  --git a/llvm/test/CodeGen/PowerPC/test_func_desc.ll b/llvm/test/CodeGen/PowerPC/test_func_desc.ll
index 500be4b63d2d..4c79bafeb035 100644
--- a/llvm/test/CodeGen/PowerPC/test_func_desc.ll
+++ b/llvm/test/CodeGen/PowerPC/test_func_desc.ll
@@ -56,6 +56,7 @@ entry:
 ; CHECK: bl .extern_foo
 ; CHECK: bl .static_foo
 
+; CHECK: .lglobl static_foo[DS]
 ; CHECK: .lglobl .static_foo
 ; 32BIT: .csect static_foo[DS],2
 ; 32BIT-NEXT: .vbyte	4, .static_foo


        


More information about the llvm-commits mailing list