diff options
Diffstat (limited to 'llvm/lib/MC')
-rw-r--r-- | llvm/lib/MC/WinCOFFObjectWriter.cpp | 72 |
1 files changed, 40 insertions, 32 deletions
diff --git a/llvm/lib/MC/WinCOFFObjectWriter.cpp b/llvm/lib/MC/WinCOFFObjectWriter.cpp index cb5998437b0..ac4a5bdcd50 100644 --- a/llvm/lib/MC/WinCOFFObjectWriter.cpp +++ b/llvm/lib/MC/WinCOFFObjectWriter.cpp @@ -155,6 +155,8 @@ public: object_t *createCOFFEntity(StringRef Name, list_t &List); void defineSection(MCSectionCOFF const &Sec); + + COFFSymbol *getLinkedSymbol(const MCSymbol &Symbol); void DefineSymbol(const MCSymbol &Symbol, MCAssembler &Assembler, const MCAsmLayout &Layout); @@ -353,6 +355,21 @@ static uint64_t getSymbolValue(const MCSymbol &Symbol, return Res; } +COFFSymbol *WinCOFFObjectWriter::getLinkedSymbol(const MCSymbol &Symbol) { + if (!Symbol.isVariable()) + return nullptr; + + const MCSymbolRefExpr *SymRef = + dyn_cast<MCSymbolRefExpr>(Symbol.getVariableValue()); + if (!SymRef) + return nullptr; + + const MCSymbol &Aliasee = SymRef->getSymbol(); + if (!Aliasee.isUndefined()) + return nullptr; + return GetOrCreateCOFFSymbol(&Aliasee); +} + /// This function takes a symbol data object from the assembler /// and creates the associated COFF symbol staging object. void WinCOFFObjectWriter::DefineSymbol(const MCSymbol &Symbol, @@ -367,32 +384,23 @@ void WinCOFFObjectWriter::DefineSymbol(const MCSymbol &Symbol, report_fatal_error("conflicting sections for symbol"); } + COFFSymbol *Local = nullptr; if (cast<MCSymbolCOFF>(Symbol).isWeakExternal()) { coff_symbol->Data.StorageClass = COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL; - if (Symbol.isVariable()) { - const MCSymbolRefExpr *SymRef = - dyn_cast<MCSymbolRefExpr>(Symbol.getVariableValue()); - - if (!SymRef) - report_fatal_error("Weak externals may only alias symbols"); - - coff_symbol->Other = GetOrCreateCOFFSymbol(&SymRef->getSymbol()); - } else { + COFFSymbol *WeakDefault = getLinkedSymbol(Symbol); + if (!WeakDefault) { std::string WeakName = (".weak." + Symbol.getName() + ".default").str(); - COFFSymbol *WeakDefault = createSymbol(WeakName); - + WeakDefault = createSymbol(WeakName); if (!Sec) WeakDefault->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE; else WeakDefault->Section = Sec; - - WeakDefault->Data.StorageClass = COFF::IMAGE_SYM_CLASS_EXTERNAL; - WeakDefault->Data.Type = 0; - WeakDefault->Data.Value = getSymbolValue(Symbol, Layout); - coff_symbol->Other = WeakDefault; + Local = WeakDefault; } + coff_symbol->Other = WeakDefault; + // Setup the Weak External auxiliary symbol. coff_symbol->Aux.resize(1); memset(&coff_symbol->Aux[0], 0, sizeof(coff_symbol->Aux[0])); @@ -400,32 +408,32 @@ void WinCOFFObjectWriter::DefineSymbol(const MCSymbol &Symbol, coff_symbol->Aux[0].Aux.WeakExternal.TagIndex = 0; coff_symbol->Aux[0].Aux.WeakExternal.Characteristics = COFF::IMAGE_WEAK_EXTERN_SEARCH_LIBRARY; - - coff_symbol->MC = &Symbol; } else { - coff_symbol->Data.Value = getSymbolValue(Symbol, Layout); + if (!Base) + coff_symbol->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE; + else + coff_symbol->Section = Sec; + Local = coff_symbol; + } + + if (Local) { + Local->Data.Value = getSymbolValue(Symbol, Layout); const MCSymbolCOFF &SymbolCOFF = cast<MCSymbolCOFF>(Symbol); - coff_symbol->Data.Type = SymbolCOFF.getType(); - coff_symbol->Data.StorageClass = SymbolCOFF.getClass(); + Local->Data.Type = SymbolCOFF.getType(); + Local->Data.StorageClass = SymbolCOFF.getClass(); // If no storage class was specified in the streamer, define it here. - if (coff_symbol->Data.StorageClass == COFF::IMAGE_SYM_CLASS_NULL) { + if (Local->Data.StorageClass == COFF::IMAGE_SYM_CLASS_NULL) { bool IsExternal = Symbol.isExternal() || (!Symbol.getFragment() && !Symbol.isVariable()); - coff_symbol->Data.StorageClass = IsExternal - ? COFF::IMAGE_SYM_CLASS_EXTERNAL - : COFF::IMAGE_SYM_CLASS_STATIC; + Local->Data.StorageClass = IsExternal ? COFF::IMAGE_SYM_CLASS_EXTERNAL + : COFF::IMAGE_SYM_CLASS_STATIC; } - - if (!Base) - coff_symbol->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE; - else - coff_symbol->Section = Sec; - - coff_symbol->MC = &Symbol; } + + coff_symbol->MC = &Symbol; } // Maximum offsets for different string table entry encodings. |