diff options
Diffstat (limited to 'llvm/lib/MC')
-rw-r--r-- | llvm/lib/MC/MCAsmStreamer.cpp | 12 | ||||
-rw-r--r-- | llvm/lib/MC/MCAssembler.cpp | 43 | ||||
-rw-r--r-- | llvm/lib/MC/MCContext.cpp | 5 | ||||
-rw-r--r-- | llvm/lib/MC/MCELFStreamer.cpp | 21 | ||||
-rw-r--r-- | llvm/lib/MC/MCObjectStreamer.cpp | 142 | ||||
-rw-r--r-- | llvm/lib/MC/MCParser/AsmParser.cpp | 9 |
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; } |