diff --git a/llvm/include/llvm/MC/MCAsmInfo.h b/llvm/include/llvm/MC/MCAsmInfo.h --- a/llvm/include/llvm/MC/MCAsmInfo.h +++ b/llvm/include/llvm/MC/MCAsmInfo.h @@ -343,10 +343,6 @@ /// 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 @@ 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 --- a/llvm/include/llvm/MC/MCContext.h +++ b/llvm/include/llvm/MC/MCContext.h @@ -57,6 +57,7 @@ class MCSymbol; class MCSymbolELF; class MCSymbolWasm; + class MCSymbolXCOFF; class SMLoc; class SourceMgr; @@ -308,6 +309,9 @@ unsigned UniqueID, const MCSymbolELF *LinkedToSym); + MCSymbolXCOFF *createXCOFFSymbolImpl(const StringMapEntry *Name, + bool IsTemporary); + /// Map of currently defined macros. StringMap MacroMap; diff --git a/llvm/include/llvm/MC/MCSectionXCOFF.h b/llvm/include/llvm/MC/MCSectionXCOFF.h --- a/llvm/include/llvm/MC/MCSectionXCOFF.h +++ b/llvm/include/llvm/MC/MCSectionXCOFF.h @@ -36,13 +36,15 @@ 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 @@ 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 --- a/llvm/include/llvm/MC/MCStreamer.h +++ b/llvm/include/llvm/MC/MCStreamer.h @@ -574,6 +574,16 @@ 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 --- a/llvm/include/llvm/MC/MCSymbolXCOFF.h +++ b/llvm/include/llvm/MC/MCSymbolXCOFF.h @@ -24,6 +24,16 @@ 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 @@ 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 @@ 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 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 --- a/llvm/include/llvm/MC/MCXCOFFStreamer.h +++ b/llvm/include/llvm/MC/MCXCOFFStreamer.h @@ -32,6 +32,11 @@ 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 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -682,8 +682,7 @@ 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 --- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -2168,6 +2168,6 @@ MCSection *TargetLoweringObjectFileXCOFF::getSectionForTOCEntry( const MCSymbol *Sym) const { return getContext().getXCOFFSection( - cast(Sym)->getUnqualifiedName(), XCOFF::XMC_TC, + cast(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 --- 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 @@ COMMDirectiveAlignmentIsInBytes = false; LCOMMDirectiveAlignmentType = LCOMM::Log2Alignment; HasDotTypeDotSizeDirective = false; - SymbolsHaveSMC = true; UseIntegratedAssembler = false; NeedsFunctionDescriptors = true; } @@ -43,5 +43,8 @@ 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 --- 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 @@ 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::emitXCOFFSymbolLinkageWithVisibility( MCSymbol *Symbol, MCSymbolAttr Linkage, MCSymbolAttr Visibility) { + // Print symbol's rename (original name contains invalid character(s)) if + // there is one. + if (cast(Symbol)->hasRename()) + emitXCOFFRenameDirective(Symbol, + cast(Symbol)->getSymbolTableName()); switch (Linkage) { case MCSA_Global: @@ -808,6 +816,9 @@ 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 @@ 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::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(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 --- a/llvm/lib/MC/MCContext.cpp +++ b/llvm/lib/MC/MCContext.cpp @@ -182,7 +182,7 @@ 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 @@ InlineAsmUsedLabelNames[Sym->getName()] = Sym; } +MCSymbolXCOFF * +MCContext::createXCOFFSymbolImpl(const StringMapEntry *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 @@ // Otherwise, return a new section. StringRef CachedName = Entry.first.SectionName; - MCSymbol *QualName = getOrCreateSymbol( - CachedName + "[" + XCOFF::getMappingClassString(SMC) + "]"); + MCSymbolXCOFF *QualName = cast(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(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 --- a/llvm/lib/MC/MCStreamer.cpp +++ b/llvm/lib/MC/MCStreamer.cpp @@ -1071,6 +1071,12 @@ "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 --- a/llvm/lib/MC/MCSymbolXCOFF.cpp +++ b/llvm/lib/MC/MCSymbolXCOFF.cpp @@ -17,6 +17,9 @@ 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 @@ 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 --- a/llvm/lib/MC/XCOFFObjectWriter.cpp +++ b/llvm/lib/MC/XCOFFObjectWriter.cpp @@ -68,7 +68,7 @@ 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 @@ SmallVector Syms; SmallVector 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 @@ // 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 @@ // 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 @@ // 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 @@ 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(CSectionRef.Address + SymbolOffset); @@ -592,7 +592,7 @@ 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(CSectionRef.Address); // n_scnum diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp --- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp +++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp @@ -120,14 +120,17 @@ : PPCTargetStreamer(S), OS(OS) {} void emitTCEntry(const MCSymbol &S) override { - const MCAsmInfo *MAI = Streamer.getContext().getAsmInfo(); - OS << "\t.tc "; - OS << (MAI->getSymbolsHaveSMC() - ? cast(S).getUnqualifiedName() - : S.getName()); - OS << "[TC],"; - OS << S.getName(); - OS << '\n'; + if (const MCSymbolXCOFF *XSym = dyn_cast(&S)) { + MCSymbolXCOFF *TCSym = + cast(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 --- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -1608,8 +1608,10 @@ 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 @@ 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 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -5345,7 +5345,7 @@ // 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 --- /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@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@o" +; ASM-NEXT: .extern ._Renamed..40f_o +; ASM-NEXT: .rename _Renamed..40f_o[DS],"f@o" +; ASM-NEXT: .extern _Renamed..40f_o[DS] +; ASM-NEXT: .toc +; ASM-NEXT: L..C0: +; ASM-NEXT: .rename _Renamed..40f_o[TC],"f@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@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@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 +; OBJ-EMPTY: +; OBJ-NEXT: 0000005c (idx: 16) f$o[DS]: +; OBJ-NEXT: 5c: 00 00 00 00 +; OBJ-NEXT: 0000005c: R_POS (idx: 6) .f$o +; OBJ-NEXT: 60: 00 00 00 80 +; OBJ-NEXT: 00000060: R_POS (idx: 22) TOC[TC0] +; OBJ-NEXT: 64: 00 00 00 00 +; OBJ-EMPTY: +; OBJ-NEXT: 00000068 (idx: 18) f&o[DS]: +; OBJ-NEXT: 68: 00 00 00 30 +; OBJ-NEXT: 00000068: R_POS (idx: 8) .f&o +; OBJ-NEXT: 6c: 00 00 00 80 +; OBJ-NEXT: 0000006c: R_POS (idx: 22) TOC[TC0] +; OBJ-NEXT: 70: 00 00 00 00 +; OBJ-EMPTY: +; OBJ-NEXT: 00000074 (idx: 20) f&_o[DS]: +; OBJ-NEXT: 74: 00 00 00 50 +; OBJ-NEXT: 00000074: R_POS (idx: 10) .f&_o +; OBJ-NEXT: 78: 00 00 00 80 +; OBJ-NEXT: 00000078: R_POS (idx: 22) TOC[TC0] +; OBJ-NEXT: 7c: 00 00 00 00 +; OBJ-EMPTY: +; OBJ-NEXT: 00000080 (idx: 24) f@o[TC]: +; OBJ-NEXT: 80: 00 00 00 00 +; OBJ-NEXT: 00000080: R_POS (idx: 2) f@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 --- a/llvm/test/CodeGen/PowerPC/test_func_desc.ll +++ b/llvm/test/CodeGen/PowerPC/test_func_desc.ll @@ -56,6 +56,7 @@ ; 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