diff --git a/llvm/lib/MC/ELFObjectWriter.cpp b/llvm/lib/MC/ELFObjectWriter.cpp --- a/llvm/lib/MC/ELFObjectWriter.cpp +++ b/llvm/lib/MC/ELFObjectWriter.cpp @@ -547,9 +547,27 @@ uint64_t Size = 0; const MCExpr *ESize = MSD.Symbol->getSize(); - if (!ESize && Base) + if (!ESize && Base) { + // For expressions like .set y, x+1, if y's size is unset, inherit from x. ESize = Base->getSize(); + // For `.size x, 2; y = x; .size y, 1; z = y; z1 = z; .symver y, y@v1`, z, + // z1, and y@v1's st_size equals y's. However, `Base` is `x` which will give + // us 2. Follow the MCSymbolRefExpr assignment chain, which covers most + // needs. MCBinaryExpr is not handled. + const MCSymbolELF *Sym = &Symbol; + while (Sym->isVariable()) { + if (auto *Expr = + dyn_cast(Sym->getVariableValue(false))) { + Sym = cast(&Expr->getSymbol()); + if (!Sym->getSize()) + continue; + ESize = Sym->getSize(); + } + break; + } + } + if (ESize) { int64_t Res; if (!ESize->evaluateKnownAbsolute(Res, Layout)) diff --git a/llvm/test/MC/ELF/offset.s b/llvm/test/MC/ELF/offset.s --- a/llvm/test/MC/ELF/offset.s +++ b/llvm/test/MC/ELF/offset.s @@ -14,15 +14,15 @@ # CHECK-NEXT: 000000000000000d 42 OBJECT GLOBAL DEFAULT [[#A]] d1 # CHECK-NEXT: 000000000000000d 42 OBJECT GLOBAL DEFAULT [[#A]] d2 # CHECK-NEXT: 0000000000000001 41 OBJECT GLOBAL DEFAULT [[#A]] e -# CHECK-NEXT: 0000000000000001 42 OBJECT GLOBAL DEFAULT [[#A]] e1 -# CHECK-NEXT: 0000000000000001 42 OBJECT GLOBAL DEFAULT [[#A]] e2 +# CHECK-NEXT: 0000000000000001 41 OBJECT GLOBAL DEFAULT [[#A]] e1 +# CHECK-NEXT: 0000000000000001 41 OBJECT GLOBAL DEFAULT [[#A]] e2 # CHECK-NEXT: 0000000000000002 42 OBJECT GLOBAL DEFAULT [[#A]] e3 # CHECK-NEXT: 0000000000000005 0 NOTYPE GLOBAL DEFAULT [[#A]] test2_a # CHECK-NEXT: 0000000000000005 0 NOTYPE GLOBAL DEFAULT [[#A]] test2_b # CHECK-NEXT: 0000000000000009 0 NOTYPE GLOBAL DEFAULT [[#A]] test2_c # CHECK-NEXT: 0000000000000009 0 NOTYPE GLOBAL DEFAULT [[#A]] test2_d # CHECK-NEXT: 0000000000000004 0 NOTYPE GLOBAL DEFAULT ABS test2_e -# CHECK-NEXT: 0000000000000001 42 OBJECT GLOBAL DEFAULT [[#A]] e@v1 +# CHECK-NEXT: 0000000000000001 41 OBJECT GLOBAL DEFAULT [[#A]] e@v1 .data @@ -45,7 +45,8 @@ e = a + (1 - 1) .size e, 41 -## FIXME These st_size fields inherit from e instead of a. +## These st_size fields inherit from e instead of a. +## TODO e3's st_size should inherit from e. .set e1, e .set e2, e1 e3 = e1 + 1