forked from OSchip/llvm-project
[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
This commit is contained in:
parent
e80b81d1cb
commit
6d3ae365bd
|
@ -343,10 +343,6 @@ protected:
|
|||
/// 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 @@ public:
|
|||
return ProtectedVisibilityAttr;
|
||||
}
|
||||
|
||||
bool getSymbolsHaveSMC() const { return SymbolsHaveSMC; }
|
||||
|
||||
bool doesSupportDebugInformation() const { return SupportsDebugInformation; }
|
||||
|
||||
bool doesSupportExceptionHandling() const {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 @@ public:
|
|||
const MCExpr *Subsection) const override;
|
||||
bool UseCodeAlign() const override;
|
||||
bool isVirtualSection() const override;
|
||||
StringRef getSymbolTableName() const { return SymbolTableName; }
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
|
|
@ -574,6 +574,16 @@ public:
|
|||
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:
|
||||
|
|
|
@ -24,6 +24,16 @@ public:
|
|||
|
||||
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 @@ public:
|
|||
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 @@ public:
|
|||
|
||||
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
|
||||
|
|
|
@ -32,6 +32,11 @@ public:
|
|||
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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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 == '.';
|
||||
}
|
||||
|
|
|
@ -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 @@ public:
|
|||
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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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) {}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -120,14 +120,17 @@ public:
|
|||
: 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 {
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 <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@o[TC]:
|
||||
; OBJ-NEXT: 80: 00 00 00 00 <unknown>
|
||||
; 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: ...
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue