diff options
author | Rafael Espindola <rafael.espindola@gmail.com> | 2015-03-25 13:16:53 +0000 |
---|---|---|
committer | Rafael Espindola <rafael.espindola@gmail.com> | 2015-03-25 13:16:53 +0000 |
commit | f275ad8af13d2e539dfa6ee882ef89a885e4164a (patch) | |
tree | 2dbc98d23aeeaecd464753bc5a09f3af0391f371 /llvm/lib | |
parent | 235838e1b8ab36e139b190780c2ac5f3e2f86101 (diff) | |
download | bcm5719-llvm-f275ad8af13d2e539dfa6ee882ef89a885e4164a.tar.gz bcm5719-llvm-f275ad8af13d2e539dfa6ee882ef89a885e4164a.zip |
Fix fixup evaluation when deciding what to relocate with.
The previous logic was to first try without relocations at all
and failing that stop on the first defined symbol.
That was inefficient and incorrect in the case part of the
expression could be simplified and another part could not
(see included test).
We now stop the evaluation when we get to a variable whose value
can change (i.e. is weak).
llvm-svn: 233187
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/MC/ELFObjectWriter.cpp | 10 | ||||
-rw-r--r-- | llvm/lib/MC/MCAssembler.cpp | 18 | ||||
-rw-r--r-- | llvm/lib/MC/MCExpr.cpp | 68 | ||||
-rw-r--r-- | llvm/lib/MC/MCObjectWriter.cpp | 2 |
4 files changed, 43 insertions, 55 deletions
diff --git a/llvm/lib/MC/ELFObjectWriter.cpp b/llvm/lib/MC/ELFObjectWriter.cpp index 0bc17ef3543..c99a3ee5e26 100644 --- a/llvm/lib/MC/ELFObjectWriter.cpp +++ b/llvm/lib/MC/ELFObjectWriter.cpp @@ -312,6 +312,8 @@ class ELFObjectWriter : public MCObjectWriter { bool InSet, bool IsPCRel) const override; + bool isWeak(const MCSymbolData &SD) const override; + void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) override; void writeSection(MCAssembler &Asm, const SectionIndexMapTy &SectionIndexMap, @@ -847,7 +849,7 @@ void ELFObjectWriter::RecordRelocation(MCAssembler &Asm, Fixup.getLoc(), "Cannot represent a difference across sections"); const MCSymbolData &SymBD = Asm.getSymbolData(SymB); - if (isWeak(SymBD)) + if (::isWeak(SymBD)) Asm.getContext().FatalError( Fixup.getLoc(), "Cannot represent a subtraction with a weak symbol"); @@ -1817,12 +1819,16 @@ ELFObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, const MCFragment &FB, bool InSet, bool IsPCRel) const { - if (isWeak(DataA)) + if (::isWeak(DataA)) return false; return MCObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl( Asm, DataA, FB,InSet, IsPCRel); } +bool ELFObjectWriter::isWeak(const MCSymbolData &SD) const { + return ::isWeak(SD); +} + MCObjectWriter *llvm::createELFObjectWriter(MCELFObjectTargetWriter *MOTW, raw_ostream &OS, bool IsLittleEndian) { diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp index 6ba66762177..6345bd53417 100644 --- a/llvm/lib/MC/MCAssembler.cpp +++ b/llvm/lib/MC/MCAssembler.cpp @@ -142,7 +142,7 @@ static bool getSymbolOffsetImpl(const MCAsmLayout &Layout, // If SD is a variable, evaluate it. MCValue Target; - if (!S.getVariableValue()->EvaluateAsValue(Target, &Layout, nullptr)) + if (!S.getVariableValue()->EvaluateAsRelocatable(Target, &Layout, nullptr)) report_fatal_error("unable to evaluate offset for variable '" + S.getName() + "'"); @@ -188,7 +188,7 @@ const MCSymbol *MCAsmLayout::getBaseSymbol(const MCSymbol &Symbol) const { const MCExpr *Expr = Symbol.getVariableValue(); MCValue Value; - if (!Expr->EvaluateAsValue(Value, this, nullptr)) + if (!Expr->EvaluateAsRelocatable(Value, this, nullptr)) llvm_unreachable("Invalid Expression"); const MCSymbolRefExpr *RefB = Value.getSymB(); @@ -473,18 +473,6 @@ const MCSymbolData *MCAssembler::getAtom(const MCSymbolData *SD) const { return SD->getFragment()->getAtom(); } -// Try to fully compute Expr to an absolute value and if that fails produce -// a relocatable expr. -// FIXME: Should this be the behavior of EvaluateAsRelocatable itself? -static bool evaluate(const MCExpr &Expr, const MCAsmLayout &Layout, - const MCFixup &Fixup, MCValue &Target) { - if (Expr.EvaluateAsValue(Target, &Layout, &Fixup)) { - if (Target.isAbsolute()) - return true; - } - return Expr.EvaluateAsRelocatable(Target, &Layout, &Fixup); -} - bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout, const MCFixup &Fixup, const MCFragment *DF, MCValue &Target, uint64_t &Value) const { @@ -494,7 +482,7 @@ bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout, // probably merge the two into a single callback that tries to evaluate a // fixup and records a relocation if one is needed. const MCExpr *Expr = Fixup.getValue(); - if (!evaluate(*Expr, Layout, Fixup, Target)) + if (!Expr->EvaluateAsRelocatable(Target, &Layout, &Fixup)) getContext().FatalError(Fixup.getLoc(), "expected relocatable expression"); bool IsPCRel = Backend.getFixupKindInfo( diff --git a/llvm/lib/MC/MCExpr.cpp b/llvm/lib/MC/MCExpr.cpp index cac5110a4ff..f6350e2744c 100644 --- a/llvm/lib/MC/MCExpr.cpp +++ b/llvm/lib/MC/MCExpr.cpp @@ -432,8 +432,8 @@ bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm, return true; } - bool IsRelocatable = EvaluateAsRelocatableImpl( - Value, Asm, Layout, nullptr, Addrs, InSet, /*ForceVarExpansion*/ true); + bool IsRelocatable = + EvaluateAsRelocatableImpl(Value, Asm, Layout, nullptr, Addrs, InSet); // Record the current value. Res = Value.getConstant(); @@ -586,21 +586,21 @@ bool MCExpr::EvaluateAsRelocatable(MCValue &Res, const MCFixup *Fixup) const { MCAssembler *Assembler = Layout ? &Layout->getAssembler() : nullptr; return EvaluateAsRelocatableImpl(Res, Assembler, Layout, Fixup, nullptr, - false, /*ForceVarExpansion*/ false); + false); } -bool MCExpr::EvaluateAsValue(MCValue &Res, const MCAsmLayout *Layout, - const MCFixup *Fixup) const { - MCAssembler *Assembler = Layout ? &Layout->getAssembler() : nullptr; - return EvaluateAsRelocatableImpl(Res, Assembler, Layout, Fixup, nullptr, - false, /*ForceVarExpansion*/ true); +static bool canExpand(const MCSymbol &Sym, const MCAssembler *Asm) { + if (!Asm) + return false; + const MCSymbolData &SD = Asm->getSymbolData(Sym); + return !Asm->getWriter().isWeak(SD); } bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, const MCAsmLayout *Layout, const MCFixup *Fixup, - const SectionAddrMap *Addrs, bool InSet, - bool ForceVarExpansion) const { + const SectionAddrMap *Addrs, + bool InSet) const { ++stats::MCExprEvaluate; switch (getKind()) { @@ -617,28 +617,23 @@ bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, const MCSymbol &Sym = SRE->getSymbol(); // Evaluate recursively if this is a variable. - if (Sym.isVariable() && SRE->getKind() == MCSymbolRefExpr::VK_None) { + if (Sym.isVariable() && SRE->getKind() == MCSymbolRefExpr::VK_None && + canExpand(Sym, Asm)) { if (Sym.getVariableValue()->EvaluateAsRelocatableImpl( - Res, Asm, Layout, Fixup, Addrs, true, ForceVarExpansion)) { + Res, Asm, Layout, Fixup, Addrs, true)) { + if (!SRE->hasSubsectionsViaSymbols()) + return true; + const MCSymbolRefExpr *A = Res.getSymA(); const MCSymbolRefExpr *B = Res.getSymB(); - - if (SRE->hasSubsectionsViaSymbols()) { - // FIXME: This is small hack. Given - // a = b + 4 - // .long a - // the OS X assembler will completely drop the 4. We should probably - // include it in the relocation or produce an error if that is not - // possible. - if (!A && !B) - return true; - } else { - if (ForceVarExpansion) - return true; - bool IsSymbol = A && A->getSymbol().isDefined(); - if (!IsSymbol) - return true; - } + // FIXME: This is small hack. Given + // a = b + 4 + // .long a + // the OS X assembler will completely drop the 4. We should probably + // include it in the relocation or produce an error if that is not + // possible. + if (!A && !B) + return true; } } @@ -650,9 +645,8 @@ bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, const MCUnaryExpr *AUE = cast<MCUnaryExpr>(this); MCValue Value; - if (!AUE->getSubExpr()->EvaluateAsRelocatableImpl(Value, Asm, Layout, - Fixup, Addrs, InSet, - ForceVarExpansion)) + if (!AUE->getSubExpr()->EvaluateAsRelocatableImpl(Value, Asm, Layout, Fixup, + Addrs, InSet)) return false; switch (AUE->getOpcode()) { @@ -685,12 +679,10 @@ bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, const MCBinaryExpr *ABE = cast<MCBinaryExpr>(this); MCValue LHSValue, RHSValue; - if (!ABE->getLHS()->EvaluateAsRelocatableImpl(LHSValue, Asm, Layout, - Fixup, Addrs, InSet, - ForceVarExpansion) || - !ABE->getRHS()->EvaluateAsRelocatableImpl(RHSValue, Asm, Layout, - Fixup, Addrs, InSet, - ForceVarExpansion)) + if (!ABE->getLHS()->EvaluateAsRelocatableImpl(LHSValue, Asm, Layout, Fixup, + Addrs, InSet) || + !ABE->getRHS()->EvaluateAsRelocatableImpl(RHSValue, Asm, Layout, Fixup, + Addrs, InSet)) return false; // We only support a few operations on non-constant expressions, handle diff --git a/llvm/lib/MC/MCObjectWriter.cpp b/llvm/lib/MC/MCObjectWriter.cpp index 94d7cd6fd4f..55bdd0b8439 100644 --- a/llvm/lib/MC/MCObjectWriter.cpp +++ b/llvm/lib/MC/MCObjectWriter.cpp @@ -54,3 +54,5 @@ MCObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, // On ELF and COFF A - B is absolute if A and B are in the same section. return &SecA == &SecB; } + +bool MCObjectWriter::isWeak(const MCSymbolData &SD) const { return false; } |