aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/MC
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/MC')
-rw-r--r--llvm/lib/MC/MCAsmStreamer.cpp12
-rw-r--r--llvm/lib/MC/MCAssembler.cpp43
-rw-r--r--llvm/lib/MC/MCContext.cpp5
-rw-r--r--llvm/lib/MC/MCELFStreamer.cpp21
-rw-r--r--llvm/lib/MC/MCObjectStreamer.cpp142
-rw-r--r--llvm/lib/MC/MCParser/AsmParser.cpp9
6 files changed, 66 insertions, 166 deletions
diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp
index 3a330db..67c53e0 100644
--- a/llvm/lib/MC/MCAsmStreamer.cpp
+++ b/llvm/lib/MC/MCAsmStreamer.cpp
@@ -407,9 +407,8 @@ public:
const MCPseudoProbeInlineStack &InlineStack,
MCSymbol *FnSym) override;
- std::optional<std::pair<bool, std::string>>
- emitRelocDirective(const MCExpr &Offset, StringRef Name, const MCExpr *Expr,
- SMLoc Loc, const MCSubtargetInfo &STI) override;
+ void emitRelocDirective(const MCExpr &Offset, StringRef Name,
+ const MCExpr *Expr, SMLoc Loc) override;
void emitAddrsig() override;
void emitAddrsigSym(const MCSymbol *Sym) override;
@@ -2468,10 +2467,8 @@ void MCAsmStreamer::emitPseudoProbe(uint64_t Guid, uint64_t Index,
EmitEOL();
}
-std::optional<std::pair<bool, std::string>>
-MCAsmStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name,
- const MCExpr *Expr, SMLoc,
- const MCSubtargetInfo &STI) {
+void MCAsmStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name,
+ const MCExpr *Expr, SMLoc) {
OS << "\t.reloc ";
MAI->printExpr(OS, Offset);
OS << ", " << Name;
@@ -2480,7 +2477,6 @@ MCAsmStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name,
MAI->printExpr(OS, *Expr);
}
EmitEOL();
- return std::nullopt;
}
void MCAsmStreamer::emitAddrsig() {
diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp
index d4d10e0..3e96bdf 100644
--- a/llvm/lib/MC/MCAssembler.cpp
+++ b/llvm/lib/MC/MCAssembler.cpp
@@ -398,6 +398,10 @@ bool MCAssembler::registerSymbol(const MCSymbol &Symbol) {
return Changed;
}
+void MCAssembler::addRelocDirective(RelocDirective RD) {
+ relocDirectives.push_back(RD);
+}
+
/// Write the fragment \p F to the output file.
static void writeFragment(raw_ostream &OS, const MCAssembler &Asm,
const MCFragment &F) {
@@ -695,6 +699,27 @@ void MCAssembler::layout() {
// helps check whether a PC-relative fixup is fully resolved.
this->HasFinalLayout = true;
+ // Resolve .reloc offsets and add fixups.
+ for (auto &PF : relocDirectives) {
+ MCValue Res;
+ auto &O = PF.Offset;
+ if (!O.evaluateAsValue(Res, *this)) {
+ getContext().reportError(O.getLoc(), ".reloc offset is not relocatable");
+ continue;
+ }
+ auto *Sym = Res.getAddSym();
+ auto *F = Sym ? Sym->getFragment() : nullptr;
+ auto *Sec = F ? F->getParent() : nullptr;
+ if (Res.getSubSym() || !Sec) {
+ getContext().reportError(O.getLoc(),
+ ".reloc offset is not relative to a section");
+ continue;
+ }
+
+ uint64_t Offset = Sym ? Sym->getOffset() + Res.getConstant() : 0;
+ F->addFixup(MCFixup::create(Offset, PF.Expr, PF.Kind));
+ }
+
// Evaluate and apply the fixups, generating relocation entries as necessary.
for (MCSection &Sec : *this) {
for (MCFragment &F : Sec) {
@@ -710,13 +735,17 @@ void MCAssembler::layout() {
// In the variable part, fixup offsets are relative to the fixed part's
// start. Extend the variable contents to the left to account for the
// fixed part size.
- Contents = MutableArrayRef(F.getParent()->ContentStorage)
- .slice(F.VarContentStart - Contents.size(), F.getSize());
- for (MCFixup &Fixup : F.getVarFixups()) {
- uint64_t FixedValue;
- MCValue Target;
- evaluateFixup(F, Fixup, Target, FixedValue,
- /*RecordReloc=*/true, Contents);
+ auto VarFixups = F.getVarFixups();
+ if (VarFixups.size()) {
+ Contents =
+ MutableArrayRef(F.getParent()->ContentStorage)
+ .slice(F.VarContentStart - Contents.size(), F.getSize());
+ for (MCFixup &Fixup : VarFixups) {
+ uint64_t FixedValue;
+ MCValue Target;
+ evaluateFixup(F, Fixup, Target, FixedValue,
+ /*RecordReloc=*/true, Contents);
+ }
}
} else if (auto *AF = dyn_cast<MCAlignFragment>(&F)) {
// For RISC-V linker relaxation, an alignment relocation might be
diff --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp
index 070be62..12b3fba 100644
--- a/llvm/lib/MC/MCContext.cpp
+++ b/llvm/lib/MC/MCContext.cpp
@@ -734,9 +734,8 @@ MCSectionGOFF *MCContext::getGOFFSection(SectionKind Kind, StringRef Name,
UniqueName.append("/").append(P->getName());
}
// Do the lookup. If we don't have a hit, return a new section.
- auto IterBool = GOFFUniquingMap.insert(std::make_pair(UniqueName, nullptr));
- auto Iter = IterBool.first;
- if (!IterBool.second)
+ auto [Iter, Inserted] = GOFFUniquingMap.try_emplace(UniqueName);
+ if (!Inserted)
return Iter->second;
StringRef CachedName = StringRef(Iter->first.c_str(), Name.size());
diff --git a/llvm/lib/MC/MCELFStreamer.cpp b/llvm/lib/MC/MCELFStreamer.cpp
index ffc5722..49071bd 100644
--- a/llvm/lib/MC/MCELFStreamer.cpp
+++ b/llvm/lib/MC/MCELFStreamer.cpp
@@ -314,8 +314,9 @@ void MCELFStreamer::emitIdent(StringRef IdentString) {
popSection();
}
-void MCELFStreamer::finalizeCGProfileEntry(const MCSymbolRefExpr *&SRE,
- uint64_t Offset) {
+void MCELFStreamer::finalizeCGProfileEntry(const MCSymbolRefExpr *Sym,
+ uint64_t Offset,
+ const MCSymbolRefExpr *&SRE) {
const MCSymbol *S = &SRE->getSymbol();
if (S->isTemporary()) {
if (!S->isInSection()) {
@@ -328,13 +329,9 @@ void MCELFStreamer::finalizeCGProfileEntry(const MCSymbolRefExpr *&SRE,
S->setUsedInReloc();
SRE = MCSymbolRefExpr::create(S, getContext(), SRE->getLoc());
}
- const MCConstantExpr *MCOffset = MCConstantExpr::create(Offset, getContext());
- if (std::optional<std::pair<bool, std::string>> Err =
- MCObjectStreamer::emitRelocDirective(
- *MCOffset, "BFD_RELOC_NONE", SRE, SRE->getLoc(),
- *getContext().getSubtargetInfo()))
- report_fatal_error("Relocation for CG Profile could not be created: " +
- Twine(Err->second));
+ auto *O = MCBinaryExpr::createAdd(
+ Sym, MCConstantExpr::create(Offset, getContext()), getContext());
+ MCObjectStreamer::emitRelocDirective(*O, "BFD_RELOC_NONE", SRE);
}
void MCELFStreamer::finalizeCGProfile() {
@@ -347,9 +344,11 @@ void MCELFStreamer::finalizeCGProfile() {
pushSection();
switchSection(CGProfile);
uint64_t Offset = 0;
+ auto *Sym =
+ MCSymbolRefExpr::create(CGProfile->getBeginSymbol(), getContext());
for (auto &E : W.getCGProfile()) {
- finalizeCGProfileEntry(E.From, Offset);
- finalizeCGProfileEntry(E.To, Offset);
+ finalizeCGProfileEntry(Sym, Offset, E.From);
+ finalizeCGProfileEntry(Sym, Offset, E.To);
emitIntValue(E.Count, sizeof(uint64_t));
Offset += sizeof(uint64_t);
}
diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp
index c0cef0f..67433f2 100644
--- a/llvm/lib/MC/MCObjectStreamer.cpp
+++ b/llvm/lib/MC/MCObjectStreamer.cpp
@@ -46,35 +46,6 @@ MCAssembler *MCObjectStreamer::getAssemblerPtr() {
return nullptr;
}
-// When fixup's offset is a forward declared label, e.g.:
-//
-// .reloc 1f, R_MIPS_JALR, foo
-// 1: nop
-//
-// postpone adding it to Fixups vector until the label is defined and its offset
-// is known.
-void MCObjectStreamer::resolvePendingFixups() {
- for (PendingMCFixup &PendingFixup : PendingFixups) {
- if (!PendingFixup.Sym || PendingFixup.Sym->isUndefined ()) {
- getContext().reportError(PendingFixup.Fixup.getLoc(),
- "unresolved relocation offset");
- continue;
- }
- PendingFixup.Fixup.setOffset(PendingFixup.Sym->getOffset() +
- PendingFixup.Fixup.getOffset());
-
- // If the location symbol to relocate is in MCEncodedFragment,
- // put the Fixup into location symbol's fragment. Otherwise
- // put into PendingFixup.DF
- MCFragment *F = PendingFixup.Sym->getFragment();
- if (F->isEncoded())
- F->addFixup(PendingFixup.Fixup);
- else
- PendingFixup.DF->addFixup(PendingFixup.Fixup);
- }
- PendingFixups.clear();
-}
-
// As a compile-time optimization, avoid allocating and evaluating an MCExpr
// tree for (Hi - Lo) when Hi and Lo are offsets into the same fragment's fixed
// part.
@@ -607,76 +578,14 @@ void MCObjectStreamer::emitValueToOffset(const MCExpr *Offset,
insert(getContext().allocFragment<MCOrgFragment>(*Offset, Value, Loc));
}
-static std::optional<std::pair<bool, std::string>>
-getOffsetAndDataFragment(const MCSymbol &Symbol, uint32_t &RelocOffset,
- MCFragment *&DF) {
- if (Symbol.isVariable()) {
- const MCExpr *SymbolExpr = Symbol.getVariableValue();
- MCValue OffsetVal;
- if (!SymbolExpr->evaluateAsRelocatable(OffsetVal, nullptr))
- return std::make_pair(false,
- std::string("symbol in .reloc offset is not "
- "relocatable"));
- if (OffsetVal.isAbsolute()) {
- RelocOffset = OffsetVal.getConstant();
- MCFragment *Fragment = Symbol.getFragment();
- // FIXME Support symbols with no DF. For example:
- // .reloc .data, ENUM_VALUE, <some expr>
- if (!Fragment || Fragment->getKind() != MCFragment::FT_Data)
- return std::make_pair(false,
- std::string("symbol in offset has no data "
- "fragment"));
- DF = cast<MCFragment>(Fragment);
- return std::nullopt;
- }
-
- if (OffsetVal.getSubSym())
- return std::make_pair(false,
- std::string(".reloc symbol offset is not "
- "representable"));
-
- const MCSymbol &SA = *OffsetVal.getAddSym();
- if (!SA.isDefined())
- return std::make_pair(false,
- std::string("symbol used in the .reloc offset is "
- "not defined"));
-
- if (SA.isVariable())
- return std::make_pair(false,
- std::string("symbol used in the .reloc offset is "
- "variable"));
-
- MCFragment *Fragment = SA.getFragment();
- // FIXME Support symbols with no DF. For example:
- // .reloc .data, ENUM_VALUE, <some expr>
- if (!Fragment || Fragment->getKind() != MCFragment::FT_Data)
- return std::make_pair(false,
- std::string("symbol in offset has no data "
- "fragment"));
- RelocOffset = SA.getOffset() + OffsetVal.getConstant();
- DF = cast<MCFragment>(Fragment);
- } else {
- RelocOffset = Symbol.getOffset();
- MCFragment *Fragment = Symbol.getFragment();
- // FIXME Support symbols with no DF. For example:
- // .reloc .data, ENUM_VALUE, <some expr>
- if (!Fragment || Fragment->getKind() != MCFragment::FT_Data)
- return std::make_pair(false,
- std::string("symbol in offset has no data "
- "fragment"));
- DF = cast<MCFragment>(Fragment);
- }
- return std::nullopt;
-}
-
-std::optional<std::pair<bool, std::string>>
-MCObjectStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name,
- const MCExpr *Expr, SMLoc Loc,
- const MCSubtargetInfo &STI) {
+void MCObjectStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name,
+ const MCExpr *Expr, SMLoc Loc) {
std::optional<MCFixupKind> MaybeKind =
Assembler->getBackend().getFixupKind(Name);
- if (!MaybeKind)
- return std::make_pair(true, std::string("unknown relocation name"));
+ if (!MaybeKind) {
+ getContext().reportError(Loc, "unknown relocation name");
+ return;
+ }
MCFixupKind Kind = *MaybeKind;
if (Expr)
@@ -685,38 +594,14 @@ MCObjectStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name,
Expr =
MCSymbolRefExpr::create(getContext().createTempSymbol(), getContext());
- MCFragment *DF = getOrCreateDataFragment(&STI);
- MCValue OffsetVal;
- if (!Offset.evaluateAsRelocatable(OffsetVal, nullptr))
- return std::make_pair(false,
- std::string(".reloc offset is not relocatable"));
- if (OffsetVal.isAbsolute()) {
- if (OffsetVal.getConstant() < 0)
- return std::make_pair(false, std::string(".reloc offset is negative"));
- DF->addFixup(MCFixup::create(OffsetVal.getConstant(), Expr, Kind));
- return std::nullopt;
- }
- if (OffsetVal.getSubSym())
- return std::make_pair(false,
- std::string(".reloc offset is not representable"));
-
- const MCSymbol &Symbol = *OffsetVal.getAddSym();
- if (Symbol.isDefined()) {
- uint32_t SymbolOffset = 0;
- std::optional<std::pair<bool, std::string>> Error =
- getOffsetAndDataFragment(Symbol, SymbolOffset, DF);
-
- if (Error != std::nullopt)
- return Error;
-
- DF->addFixup(
- MCFixup::create(SymbolOffset + OffsetVal.getConstant(), Expr, Kind));
- return std::nullopt;
+ auto *O = &Offset;
+ int64_t Val;
+ if (Offset.evaluateAsAbsolute(Val, nullptr)) {
+ auto *SecSym = getCurrentSectionOnly()->getBeginSymbol();
+ O = MCBinaryExpr::createAdd(MCSymbolRefExpr::create(SecSym, getContext()),
+ O, getContext(), Loc);
}
-
- PendingFixups.emplace_back(
- &Symbol, DF, MCFixup::create(OffsetVal.getConstant(), Expr, Kind));
- return std::nullopt;
+ getAssembler().addRelocDirective({*O, Expr, Kind});
}
void MCObjectStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue,
@@ -799,6 +684,5 @@ void MCObjectStreamer::finishImpl() {
// Emit pseudo probes for the current module.
MCPseudoProbeTable::emit(this);
- resolvePendingFixups();
getAssembler().Finish();
}
diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp
index a36b2de..77bf843 100644
--- a/llvm/lib/MC/MCParser/AsmParser.cpp
+++ b/llvm/lib/MC/MCParser/AsmParser.cpp
@@ -3079,7 +3079,6 @@ bool AsmParser::parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) {
bool AsmParser::parseDirectiveReloc(SMLoc DirectiveLoc) {
const MCExpr *Offset;
const MCExpr *Expr = nullptr;
- SMLoc OffsetLoc = Lexer.getTok().getLoc();
if (parseExpression(Offset))
return true;
@@ -3105,13 +3104,7 @@ bool AsmParser::parseDirectiveReloc(SMLoc DirectiveLoc) {
if (parseEOL())
return true;
- const MCTargetAsmParser &MCT = getTargetParser();
- const MCSubtargetInfo &STI = MCT.getSTI();
- if (std::optional<std::pair<bool, std::string>> Err =
- getStreamer().emitRelocDirective(*Offset, Name, Expr, DirectiveLoc,
- STI))
- return Error(Err->first ? NameLoc : OffsetLoc, Err->second);
-
+ getStreamer().emitRelocDirective(*Offset, Name, Expr, NameLoc);
return false;
}