diff options
author | Fangrui Song <i@maskray.me> | 2025-05-26 15:08:11 -0700 |
---|---|---|
committer | Fangrui Song <i@maskray.me> | 2025-05-26 15:08:11 -0700 |
commit | 343428c666f9293ae260bbcf79130562b830b268 (patch) | |
tree | 5a22caefe88ae828b5ca0f08d4e9f19700360f4a /llvm/lib/MC/MCExpr.cpp | |
parent | 4cb25e2d37496a5f52a62a1f411a04dac20a8666 (diff) | |
download | llvm-343428c666f9293ae260bbcf79130562b830b268.zip llvm-343428c666f9293ae260bbcf79130562b830b268.tar.gz llvm-343428c666f9293ae260bbcf79130562b830b268.tar.bz2 |
MC: Detect cyclic dependency for variable symbols
We report cyclic dependency errors for variable symbols and rely on
isSymbolUsedInExpression in parseAssignmentExpression at parse time,
which does not catch all setVariableValue cases (e.g. cyclic .weakref).
Instead, add a bit to MCSymbol and check it when walking the variable
value MCExpr. When a cycle is detected when we have a final layout,
report an error and set the variable to a constant to avoid duplicate
errors.
isSymbolUsedInExpression is considered deprecated, but it is still used
by AMDGPU (#112251).
Diffstat (limited to 'llvm/lib/MC/MCExpr.cpp')
-rw-r--r-- | llvm/lib/MC/MCExpr.cpp | 28 |
1 files changed, 24 insertions, 4 deletions
diff --git a/llvm/lib/MC/MCExpr.cpp b/llvm/lib/MC/MCExpr.cpp index eef6965..6c9fc94 100644 --- a/llvm/lib/MC/MCExpr.cpp +++ b/llvm/lib/MC/MCExpr.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCExpr.h" +#include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/Statistic.h" #include "llvm/Config/llvm-config.h" #include "llvm/MC/MCAsmBackend.h" @@ -497,13 +498,25 @@ bool MCExpr::evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, case SymbolRef: { const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(this); - const MCSymbol &Sym = SRE->getSymbol(); + MCSymbol &Sym = const_cast<MCSymbol &>(SRE->getSymbol()); const auto Kind = SRE->getKind(); bool Layout = Asm && Asm->hasLayout(); // Evaluate recursively if this is a variable. + if (Sym.isResolving()) { + if (Asm && Asm->hasFinalLayout()) { + Asm->getContext().reportError( + Sym.getVariableValue()->getLoc(), + "cyclic dependency detected for symbol '" + Sym.getName() + "'"); + Sym.IsUsed = false; + Sym.setVariableValue(MCConstantExpr::create(0, Asm->getContext())); + } + return false; + } if (Sym.isVariable() && (Kind == MCSymbolRefExpr::VK_None || Layout) && canExpand(Sym, InSet)) { + Sym.setIsResolving(true); + auto _ = make_scope_exit([&] { Sym.setIsResolving(false); }); bool IsMachO = Asm && Asm->getContext().getAsmInfo()->hasSubsectionsViaSymbols(); if (Sym.getVariableValue()->evaluateAsRelocatableImpl(Res, Asm, @@ -709,9 +722,16 @@ MCFragment *MCExpr::findAssociatedFragment() const { return MCSymbol::AbsolutePseudoFragment; case SymbolRef: { - const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(this); - const MCSymbol &Sym = SRE->getSymbol(); - return Sym.getFragment(); + auto &Sym = + const_cast<MCSymbol &>(cast<MCSymbolRefExpr>(this)->getSymbol()); + if (Sym.Fragment) + return Sym.Fragment; + if (Sym.isResolving()) + return MCSymbol::AbsolutePseudoFragment; + Sym.setIsResolving(true); + auto *F = Sym.getFragment(); + Sym.setIsResolving(false); + return F; } case Unary: |