summaryrefslogtreecommitdiffstats
path: root/llvm/lib/MC
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/MC')
-rw-r--r--llvm/lib/MC/WinCOFFObjectWriter.cpp72
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.
OpenPOWER on IntegriCloud