|
15 | 15 | #include "InstPrinter/PPCInstPrinter.h"
|
16 | 16 | #include "MCTargetDesc/PPCMCAsmInfo.h"
|
17 | 17 | #include "PPCTargetStreamer.h"
|
| 18 | +#include "llvm/ADT/SmallPtrSet.h" |
18 | 19 | #include "llvm/ADT/StringRef.h"
|
19 | 20 | #include "llvm/ADT/Triple.h"
|
20 | 21 | #include "llvm/BinaryFormat/ELF.h"
|
@@ -182,16 +183,33 @@ class PPCTargetELFStreamer : public PPCTargetStreamer {
|
182 | 183 |
|
183 | 184 | void emitAssignment(MCSymbol *S, const MCExpr *Value) override {
|
184 | 185 | auto *Symbol = cast<MCSymbolELF>(S);
|
| 186 | + |
185 | 187 | // When encoding an assignment to set symbol A to symbol B, also copy
|
186 | 188 | // the st_other bits encoding the local entry point offset.
|
187 |
| - if (Value->getKind() != MCExpr::SymbolRef) |
188 |
| - return; |
189 |
| - const auto &RhsSym = cast<MCSymbolELF>( |
190 |
| - static_cast<const MCSymbolRefExpr *>(Value)->getSymbol()); |
191 |
| - unsigned Other = Symbol->getOther(); |
| 189 | + if (copyLocalEntry(Symbol, Value)) |
| 190 | + UpdateOther.insert(Symbol); |
| 191 | + else |
| 192 | + UpdateOther.erase(Symbol); |
| 193 | + } |
| 194 | + |
| 195 | + void finish() override { |
| 196 | + for (auto *Sym : UpdateOther) |
| 197 | + copyLocalEntry(Sym, Sym->getVariableValue()); |
| 198 | + } |
| 199 | + |
| 200 | +private: |
| 201 | + SmallPtrSet<MCSymbolELF *, 32> UpdateOther; |
| 202 | + |
| 203 | + bool copyLocalEntry(MCSymbolELF *D, const MCExpr *S) { |
| 204 | + auto *Ref = dyn_cast<const MCSymbolRefExpr>(S); |
| 205 | + if (!Ref) |
| 206 | + return false; |
| 207 | + const auto &RhsSym = cast<MCSymbolELF>(Ref->getSymbol()); |
| 208 | + unsigned Other = D->getOther(); |
192 | 209 | Other &= ~ELF::STO_PPC64_LOCAL_MASK;
|
193 | 210 | Other |= RhsSym.getOther() & ELF::STO_PPC64_LOCAL_MASK;
|
194 |
| - Symbol->setOther(Other); |
| 211 | + D->setOther(Other); |
| 212 | + return true; |
195 | 213 | }
|
196 | 214 | };
|
197 | 215 |
|
|
0 commit comments