summaryrefslogtreecommitdiff
path: root/llvm/lib/MC/MCContext.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/MC/MCContext.cpp')
-rw-r--r--llvm/lib/MC/MCContext.cpp205
1 files changed, 163 insertions, 42 deletions
diff --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp
index a6417113fd384..a0f9212f3b142 100644
--- a/llvm/lib/MC/MCContext.cpp
+++ b/llvm/lib/MC/MCContext.cpp
@@ -68,8 +68,8 @@ MCContext::MCContext(const MCAsmInfo *mai, const MCRegisterInfo *mri,
SecureLogFile = AsSecureLogFileName;
if (SrcMgr && SrcMgr->getNumBuffers())
- MainFileName =
- SrcMgr->getMemoryBuffer(SrcMgr->getMainFileID())->getBufferIdentifier();
+ MainFileName = std::string(SrcMgr->getMemoryBuffer(SrcMgr->getMainFileID())
+ ->getBufferIdentifier());
}
MCContext::~MCContext() {
@@ -114,6 +114,9 @@ void MCContext::reset() {
WasmUniquingMap.clear();
XCOFFUniquingMap.clear();
+ ELFEntrySizeMap.clear();
+ ELFSeenGenericMergeableSections.clear();
+
NextID.clear();
AllowTemporaryLabels = true;
DwarfLocSeen = false;
@@ -158,6 +161,16 @@ MCSymbol *MCContext::getOrCreateLSDASymbol(StringRef FuncName) {
MCSymbol *MCContext::createSymbolImpl(const StringMapEntry<bool> *Name,
bool IsTemporary) {
+ static_assert(std::is_trivially_destructible<MCSymbolCOFF>(),
+ "MCSymbol classes must be trivially destructible");
+ static_assert(std::is_trivially_destructible<MCSymbolELF>(),
+ "MCSymbol classes must be trivially destructible");
+ static_assert(std::is_trivially_destructible<MCSymbolMachO>(),
+ "MCSymbol classes must be trivially destructible");
+ static_assert(std::is_trivially_destructible<MCSymbolWasm>(),
+ "MCSymbol classes must be trivially destructible");
+ static_assert(std::is_trivially_destructible<MCSymbolXCOFF>(),
+ "MCSymbol classes must be trivially destructible");
if (MOFI) {
switch (MOFI->getObjectFileType()) {
case MCObjectFileInfo::IsCOFF:
@@ -169,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,
@@ -272,13 +285,68 @@ void MCContext::setSymbolValue(MCStreamer &Streamer,
StringRef Sym,
uint64_t Val) {
auto Symbol = getOrCreateSymbol(Sym);
- Streamer.EmitAssignment(Symbol, MCConstantExpr::create(Val, *this));
+ Streamer.emitAssignment(Symbol, MCConstantExpr::create(Val, *this));
}
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
//===----------------------------------------------------------------------===//
@@ -292,23 +360,25 @@ MCSectionMachO *MCContext::getMachOSection(StringRef Segment, StringRef Section,
// diagnosed by the client as an error.
// Form the name to look up.
- SmallString<64> Name;
- Name += Segment;
- Name.push_back(',');
- Name += Section;
+ assert(Section.size() <= 16 && "section name is too long");
+ assert(!memchr(Section.data(), '\0', Section.size()) &&
+ "section name cannot contain NUL");
// Do the lookup, if we have a hit, return it.
- MCSectionMachO *&Entry = MachOUniquingMap[Name];
- if (Entry)
- return Entry;
+ auto R = MachOUniquingMap.try_emplace((Segment + Twine(',') + Section).str());
+ if (!R.second)
+ return R.first->second;
MCSymbol *Begin = nullptr;
if (BeginSymName)
Begin = createTempSymbol(BeginSymName, false);
// Otherwise, return a new section.
- return Entry = new (MachOAllocator.Allocate()) MCSectionMachO(
- Segment, Section, TypeAndAttributes, Reserved2, Kind, Begin);
+ StringRef Name = R.first->first();
+ R.first->second = new (MachOAllocator.Allocate())
+ MCSectionMachO(Segment, Name.substr(Name.size() - Section.size()),
+ TypeAndAttributes, Reserved2, Kind, Begin);
+ return R.first->second;
}
void MCContext::renameELFSection(MCSectionELF *Section, StringRef Name) {
@@ -316,12 +386,14 @@ void MCContext::renameELFSection(MCSectionELF *Section, StringRef Name) {
if (const MCSymbol *Group = Section->getGroup())
GroupName = Group->getName();
+ // This function is only used by .debug*, which should not have the
+ // SHF_LINK_ORDER flag.
unsigned UniqueID = Section->getUniqueID();
ELFUniquingMap.erase(
- ELFSectionKey{Section->getSectionName(), GroupName, UniqueID});
- auto I = ELFUniquingMap.insert(std::make_pair(
- ELFSectionKey{Name, GroupName, UniqueID},
- Section))
+ ELFSectionKey{Section->getName(), GroupName, "", UniqueID});
+ auto I = ELFUniquingMap
+ .insert(std::make_pair(
+ ELFSectionKey{Name, GroupName, "", UniqueID}, Section))
.first;
StringRef CachedName = I->first.SectionName;
const_cast<MCSectionELF *>(Section)->setSectionName(CachedName);
@@ -332,7 +404,7 @@ MCSectionELF *MCContext::createELFSectionImpl(StringRef Section, unsigned Type,
unsigned EntrySize,
const MCSymbolELF *Group,
unsigned UniqueID,
- const MCSymbolELF *Associated) {
+ const MCSymbolELF *LinkedToSym) {
MCSymbolELF *R;
MCSymbol *&Sym = Symbols[Section];
// A section symbol can not redefine regular symbols. There may be multiple
@@ -352,7 +424,7 @@ MCSectionELF *MCContext::createELFSectionImpl(StringRef Section, unsigned Type,
R->setType(ELF::STT_SECTION);
auto *Ret = new (ELFAllocator.Allocate()) MCSectionELF(
- Section, Type, Flags, K, EntrySize, Group, UniqueID, R, Associated);
+ Section, Type, Flags, K, EntrySize, Group, UniqueID, R, LinkedToSym);
auto *F = new MCDataFragment();
Ret->getFragmentList().insert(Ret->begin(), F);
@@ -386,26 +458,29 @@ MCSectionELF *MCContext::getELFNamedSection(const Twine &Prefix,
MCSectionELF *MCContext::getELFSection(const Twine &Section, unsigned Type,
unsigned Flags, unsigned EntrySize,
const Twine &Group, unsigned UniqueID,
- const MCSymbolELF *Associated) {
+ const MCSymbolELF *LinkedToSym) {
MCSymbolELF *GroupSym = nullptr;
if (!Group.isTriviallyEmpty() && !Group.str().empty())
GroupSym = cast<MCSymbolELF>(getOrCreateSymbol(Group));
return getELFSection(Section, Type, Flags, EntrySize, GroupSym, UniqueID,
- Associated);
+ LinkedToSym);
}
MCSectionELF *MCContext::getELFSection(const Twine &Section, unsigned Type,
unsigned Flags, unsigned EntrySize,
const MCSymbolELF *GroupSym,
unsigned UniqueID,
- const MCSymbolELF *Associated) {
+ const MCSymbolELF *LinkedToSym) {
StringRef Group = "";
if (GroupSym)
Group = GroupSym->getName();
+ assert(!(LinkedToSym && LinkedToSym->getName().empty()));
// Do the lookup, if we have a hit, return it.
- auto IterBool = ELFUniquingMap.insert(
- std::make_pair(ELFSectionKey{Section.str(), Group, UniqueID}, nullptr));
+ auto IterBool = ELFUniquingMap.insert(std::make_pair(
+ ELFSectionKey{Section.str(), Group,
+ LinkedToSym ? LinkedToSym->getName() : "", UniqueID},
+ nullptr));
auto &Entry = *IterBool.first;
if (!IterBool.second)
return Entry.second;
@@ -420,16 +495,55 @@ MCSectionELF *MCContext::getELFSection(const Twine &Section, unsigned Type,
else
Kind = SectionKind::getReadOnly();
- MCSectionELF *Result = createELFSectionImpl(
- CachedName, Type, Flags, Kind, EntrySize, GroupSym, UniqueID, Associated);
+ MCSectionELF *Result =
+ createELFSectionImpl(CachedName, Type, Flags, Kind, EntrySize, GroupSym,
+ UniqueID, LinkedToSym);
Entry.second = Result;
+
+ recordELFMergeableSectionInfo(Result->getName(), Result->getFlags(),
+ Result->getUniqueID(), Result->getEntrySize());
+
return Result;
}
MCSectionELF *MCContext::createELFGroupSection(const MCSymbolELF *Group) {
return createELFSectionImpl(".group", ELF::SHT_GROUP, 0,
- SectionKind::getReadOnly(), 4, Group, ~0,
- nullptr);
+ SectionKind::getReadOnly(), 4, Group,
+ MCSection::NonUniqueID, nullptr);
+}
+
+void MCContext::recordELFMergeableSectionInfo(StringRef SectionName,
+ unsigned Flags, unsigned UniqueID,
+ unsigned EntrySize) {
+ bool IsMergeable = Flags & ELF::SHF_MERGE;
+ if (IsMergeable && (UniqueID == GenericSectionID))
+ ELFSeenGenericMergeableSections.insert(SectionName);
+
+ // For mergeable sections or non-mergeable sections with a generic mergeable
+ // section name we enter their Unique ID into the ELFEntrySizeMap so that
+ // compatible globals can be assigned to the same section.
+ if (IsMergeable || isELFGenericMergeableSection(SectionName)) {
+ ELFEntrySizeMap.insert(std::make_pair(
+ ELFEntrySizeKey{SectionName, Flags, EntrySize}, UniqueID));
+ }
+}
+
+bool MCContext::isELFImplicitMergeableSectionNamePrefix(StringRef SectionName) {
+ return SectionName.startswith(".rodata.str") ||
+ SectionName.startswith(".rodata.cst");
+}
+
+bool MCContext::isELFGenericMergeableSection(StringRef SectionName) {
+ return isELFImplicitMergeableSectionNamePrefix(SectionName) ||
+ ELFSeenGenericMergeableSections.count(SectionName);
+}
+
+Optional<unsigned> MCContext::getELFUniqueIDForEntsize(StringRef SectionName,
+ unsigned Flags,
+ unsigned EntrySize) {
+ auto I = ELFEntrySizeMap.find(
+ MCContext::ELFEntrySizeKey{SectionName, Flags, EntrySize});
+ return (I != ELFEntrySizeMap.end()) ? Optional<unsigned>(I->second) : None;
}
MCSectionCOFF *MCContext::getCOFFSection(StringRef Section,
@@ -484,13 +598,13 @@ MCSectionCOFF *MCContext::getAssociativeCOFFSection(MCSectionCOFF *Sec,
unsigned Characteristics = Sec->getCharacteristics();
if (KeySym) {
Characteristics |= COFF::IMAGE_SCN_LNK_COMDAT;
- return getCOFFSection(Sec->getSectionName(), Characteristics,
- Sec->getKind(), KeySym->getName(),
+ return getCOFFSection(Sec->getName(), Characteristics, Sec->getKind(),
+ KeySym->getName(),
COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE, UniqueID);
}
- return getCOFFSection(Sec->getSectionName(), Characteristics, Sec->getKind(),
- "", 0, UniqueID);
+ return getCOFFSection(Sec->getName(), Characteristics, Sec->getKind(), "", 0,
+ UniqueID);
}
MCSectionWasm *MCContext::getWasmSection(const Twine &Section, SectionKind K,
@@ -551,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();
@@ -583,17 +700,21 @@ void MCContext::addDebugPrefixMapEntry(const std::string &From,
void MCContext::RemapDebugPaths() {
const auto &DebugPrefixMap = this->DebugPrefixMap;
+ if (DebugPrefixMap.empty())
+ return;
+
const auto RemapDebugPath = [&DebugPrefixMap](std::string &Path) {
- for (const auto &Entry : DebugPrefixMap)
- if (StringRef(Path).startswith(Entry.first)) {
- std::string RemappedPath =
- (Twine(Entry.second) + Path.substr(Entry.first.size())).str();
- Path.swap(RemappedPath);
+ SmallString<256> P(Path);
+ for (const auto &Entry : DebugPrefixMap) {
+ if (llvm::sys::path::replace_path_prefix(P, Entry.first, Entry.second)) {
+ Path = P.str().str();
+ break;
}
+ }
};
// Remap compilation directory.
- std::string CompDir = CompilationDir.str();
+ std::string CompDir = std::string(CompilationDir.str());
RemapDebugPath(CompDir);
CompilationDir = CompDir;