aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/MC/MCExpr.cpp
diff options
context:
space:
mode:
authorFangrui Song <i@maskray.me>2025-05-26 15:08:11 -0700
committerFangrui Song <i@maskray.me>2025-05-26 15:08:11 -0700
commit343428c666f9293ae260bbcf79130562b830b268 (patch)
tree5a22caefe88ae828b5ca0f08d4e9f19700360f4a /llvm/lib/MC/MCExpr.cpp
parent4cb25e2d37496a5f52a62a1f411a04dac20a8666 (diff)
downloadllvm-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.cpp28
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: