Currently, -gsplit-dwarf and -mrelax are incompatible options in Clang. The issue is that .dwo files should not contain any relocations, as they are not processed by the linker. However, relaxable code emits relocations in DWARF for debug ranges that reside in the .dwo file when DWARF fission is enabled. This patch makes DWARF fission compatible with RISC-V relaxations. It uses the StartxEndx DWARF forms in .debug_rnglists.dwo, which allow referencing addresses from .debug_addr instead of using absolute addresses. This approach eliminates relocations from .dwo files.
105 lines
3.6 KiB
C++
105 lines
3.6 KiB
C++
//===- lib/MC/MCSymbol.cpp - MCSymbol implementation ----------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/MC/MCSymbol.h"
|
|
#include "llvm/ADT/StringRef.h"
|
|
#include "llvm/Config/llvm-config.h"
|
|
#include "llvm/MC/MCAsmInfo.h"
|
|
#include "llvm/MC/MCContext.h"
|
|
#include "llvm/Support/Compiler.h"
|
|
#include "llvm/Support/Debug.h"
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
#include <cassert>
|
|
#include <cstddef>
|
|
|
|
using namespace llvm;
|
|
|
|
// There are numerous MCSymbol objects, so keeping sizeof(MCSymbol) small is
|
|
// crucial for minimizing peak memory usage.
|
|
static_assert(sizeof(MCSymbol) <= 24, "Keep the base symbol small");
|
|
|
|
// Only the address of this fragment is ever actually used.
|
|
static MCFragment SentinelFragment;
|
|
|
|
// Sentinel value for the absolute pseudo fragment.
|
|
MCFragment *MCSymbol::AbsolutePseudoFragment = &SentinelFragment;
|
|
|
|
void *MCSymbol::operator new(size_t s, const MCSymbolTableEntry *Name,
|
|
MCContext &Ctx) {
|
|
// We may need more space for a Name to account for alignment. So allocate
|
|
// space for the storage type and not the name pointer.
|
|
size_t Size = s + (Name ? sizeof(NameEntryStorageTy) : 0);
|
|
|
|
// For safety, ensure that the alignment of a pointer is enough for an
|
|
// MCSymbol. This also ensures we don't need padding between the name and
|
|
// symbol.
|
|
static_assert((unsigned)alignof(MCSymbol) <= alignof(NameEntryStorageTy),
|
|
"Bad alignment of MCSymbol");
|
|
void *Storage = Ctx.allocate(Size, alignof(NameEntryStorageTy));
|
|
NameEntryStorageTy *Start = static_cast<NameEntryStorageTy*>(Storage);
|
|
NameEntryStorageTy *End = Start + (Name ? 1 : 0);
|
|
return End;
|
|
}
|
|
|
|
void MCSymbol::setVariableValue(const MCExpr *Value) {
|
|
assert(Value && "Invalid equated expression");
|
|
assert((kind == Kind::Regular || kind == Kind::Equated) &&
|
|
"Cannot equate a common symbol");
|
|
this->Value = Value;
|
|
kind = Kind::Equated;
|
|
Fragment = nullptr;
|
|
}
|
|
|
|
void MCSymbol::print(raw_ostream &OS, const MCAsmInfo *MAI) const {
|
|
// The name for this MCSymbol is required to be a valid target name. However,
|
|
// some targets support quoting names with funny characters. If the name
|
|
// contains a funny character, then print it quoted.
|
|
StringRef Name = getName();
|
|
if (!MAI || MAI->isValidUnquotedName(Name)) {
|
|
OS << Name;
|
|
return;
|
|
}
|
|
|
|
if (MAI && !MAI->supportsNameQuoting())
|
|
report_fatal_error("Symbol name with unsupported characters");
|
|
|
|
OS << '"';
|
|
for (char C : Name) {
|
|
if (C == '\n')
|
|
OS << "\\n";
|
|
else if (C == '"')
|
|
OS << "\\\"";
|
|
else if (C == '\\')
|
|
OS << "\\\\";
|
|
else
|
|
OS << C;
|
|
}
|
|
OS << '"';
|
|
}
|
|
|
|
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
|
|
LLVM_DUMP_METHOD void MCSymbol::dump() const { dbgs() << *this; }
|
|
#endif
|
|
|
|
// Determine whether the offset between two labels can change at link time.
|
|
// Currently, this function is used only in DWARF info emission logic, where it
|
|
// helps generate more optimal debug info when the offset between labels is
|
|
// constant at link time.
|
|
bool llvm::isRangeRelaxable(const MCSymbol *Begin, const MCSymbol *End) {
|
|
assert(Begin && "Range without a begin symbol?");
|
|
assert(End && "Range without an end symbol?");
|
|
for (const auto *Fragment = Begin->getFragment();
|
|
Fragment != End->getFragment(); Fragment = Fragment->getNext()) {
|
|
assert(Fragment);
|
|
if (Fragment->isLinkerRelaxable())
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|