From: Michael J. Spencer Date: Sat, 16 Oct 2010 08:25:57 +0000 (+0000) Subject: MC-COFF: Add support for default-null weak externals. X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=4cee2890a66974af506f2125243114cc14bd5556;p=oota-llvm.git MC-COFF: Add support for default-null weak externals. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@116666 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/Support/COFF.h b/include/llvm/Support/COFF.h index 2bba8d3c87e..46fe269a231 100644 --- a/include/llvm/Support/COFF.h +++ b/include/llvm/Support/COFF.h @@ -69,7 +69,7 @@ namespace COFF { SF_ClassMask = 0x00FF0000, SF_ClassShift = 16, - SF_WeakReference = 0x01000000 + SF_WeakExternal = 0x01000000 }; enum SymbolSectionNumber { diff --git a/lib/MC/WinCOFFObjectWriter.cpp b/lib/MC/WinCOFFObjectWriter.cpp index 285717e83e2..59cac2bc7a3 100644 --- a/lib/MC/WinCOFFObjectWriter.cpp +++ b/lib/MC/WinCOFFObjectWriter.cpp @@ -125,11 +125,8 @@ public: typedef std::vector symbols; typedef std::vector sections; - typedef StringMap name_symbol_map; - typedef StringMap name_section_map; - - typedef DenseMap symbol_map; - typedef DenseMap section_map; + typedef DenseMap symbol_map; + typedef DenseMap section_map; // Root level file contents. bool Is64Bit; @@ -145,8 +142,9 @@ public: WinCOFFObjectWriter(raw_ostream &OS, bool is64Bit); ~WinCOFFObjectWriter(); - COFFSymbol *createSymbol(llvm::StringRef Name); - COFFSection *createSection(llvm::StringRef Name); + COFFSymbol *createSymbol(StringRef Name); + COFFSymbol *GetOrCreateCOFFSymbol(const MCSymbol * Symbol); + COFFSection *createSection(StringRef Name); template object_t *createCOFFEntity(llvm::StringRef Name, list_t &List); @@ -336,10 +334,20 @@ WinCOFFObjectWriter::~WinCOFFObjectWriter() { delete *I; } -COFFSymbol *WinCOFFObjectWriter::createSymbol(llvm::StringRef Name) { +COFFSymbol *WinCOFFObjectWriter::createSymbol(StringRef Name) { return createCOFFEntity(Name, Symbols); } +COFFSymbol *WinCOFFObjectWriter::GetOrCreateCOFFSymbol(const MCSymbol * Symbol){ + symbol_map::iterator i = SymbolMap.find(Symbol); + if (i != SymbolMap.end()) + return i->second; + COFFSymbol *RetSymbol + = createCOFFEntity(Symbol->getName(), Symbols); + SymbolMap[Symbol] = RetSymbol; + return RetSymbol; +} + COFFSection *WinCOFFObjectWriter::createSection(llvm::StringRef Name) { return createCOFFEntity(Name, Sections); } @@ -402,48 +410,43 @@ void WinCOFFObjectWriter::DefineSection(MCSectionData const &SectionData) { // Bind internal COFF section to MC section. coff_section->MCData = &SectionData; - SectionMap[&SectionData] = coff_section; + SectionMap[&SectionData.getSection()] = coff_section; } /// This function takes a section data object from the assembler /// and creates the associated COFF symbol staging object. void WinCOFFObjectWriter::DefineSymbol(MCSymbolData const &SymbolData, MCAssembler &Assembler) { - assert(!SymbolData.getSymbol().isVariable() - && "Cannot define a symbol that is a variable!"); - COFFSymbol *coff_symbol = createSymbol(SymbolData.getSymbol().getName()); + COFFSymbol *coff_symbol = GetOrCreateCOFFSymbol(&SymbolData.getSymbol()); coff_symbol->Data.Type = (SymbolData.getFlags() & 0x0000FFFF) >> 0; coff_symbol->Data.StorageClass = (SymbolData.getFlags() & 0x00FF0000) >> 16; - // If no storage class was specified in the streamer, define it here. - if (coff_symbol->Data.StorageClass == 0) { - bool external = SymbolData.isExternal() || (SymbolData.Fragment == NULL); - - coff_symbol->Data.StorageClass = - external ? COFF::IMAGE_SYM_CLASS_EXTERNAL : COFF::IMAGE_SYM_CLASS_STATIC; - } - - if (SymbolData.getFlags() & COFF::SF_WeakReference) { + if (SymbolData.getFlags() & COFF::SF_WeakExternal) { coff_symbol->Data.StorageClass = COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL; - const MCExpr *Value = SymbolData.getSymbol().getVariableValue(); - - // FIXME: This assert message isn't very good. - assert(Value->getKind() == MCExpr::SymbolRef && - "Value must be a SymbolRef!"); + if (SymbolData.getSymbol().isVariable()) { + coff_symbol->Data.StorageClass = COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL; + const MCExpr *Value = SymbolData.getSymbol().getVariableValue(); - const MCSymbolRefExpr *SymbolRef = - static_cast(Value); + // FIXME: This assert message isn't very good. + assert(Value->getKind() == MCExpr::SymbolRef && + "Value must be a SymbolRef!"); - const MCSymbolData &OtherSymbolData = - Assembler.getSymbolData(SymbolRef->getSymbol()); - - // FIXME: This assert message isn't very good. - assert(SymbolMap.find(&OtherSymbolData) != SymbolMap.end() && - "OtherSymbolData must be in the symbol map!"); - - coff_symbol->Other = SymbolMap[&OtherSymbolData]; + const MCSymbolRefExpr *SymbolRef = + static_cast(Value); + coff_symbol->Other = GetOrCreateCOFFSymbol(&SymbolRef->getSymbol()); + } else { + std::string WeakName = std::string(".weak.") + + SymbolData.getSymbol().getName().str() + + ".default"; + COFFSymbol *WeakDefault = createSymbol(WeakName); + WeakDefault->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE; + WeakDefault->Data.StorageClass = COFF::IMAGE_SYM_CLASS_EXTERNAL; + WeakDefault->Data.Type = 0; + WeakDefault->Data.Value = 0; + coff_symbol->Other = WeakDefault; + } // Setup the Weak External auxiliary symbol. coff_symbol->Aux.resize(1); @@ -451,15 +454,24 @@ void WinCOFFObjectWriter::DefineSymbol(MCSymbolData const &SymbolData, coff_symbol->Aux[0].AuxType = ATWeakExternal; coff_symbol->Aux[0].Aux.WeakExternal.TagIndex = 0; coff_symbol->Aux[0].Aux.WeakExternal.Characteristics = - COFF::IMAGE_WEAK_EXTERN_SEARCH_LIBRARY; + COFF::IMAGE_WEAK_EXTERN_SEARCH_LIBRARY; + } + + // If no storage class was specified in the streamer, define it here. + if (coff_symbol->Data.StorageClass == 0) { + bool external = SymbolData.isExternal() || (SymbolData.Fragment == NULL); + + coff_symbol->Data.StorageClass = + external ? COFF::IMAGE_SYM_CLASS_EXTERNAL : COFF::IMAGE_SYM_CLASS_STATIC; } if (SymbolData.Fragment != NULL) - coff_symbol->Section = SectionMap[SymbolData.Fragment->getParent()]; + coff_symbol->Section = + SectionMap[&SymbolData.Fragment->getParent()->getSection()]; // Bind internal COFF symbol to MC symbol. coff_symbol->MCData = &SymbolData; - SymbolMap[&SymbolData] = coff_symbol; + SymbolMap[&SymbolData.getSymbol()] = coff_symbol; } /// making a section real involves assigned it a number and putting @@ -509,7 +521,7 @@ bool WinCOFFObjectWriter::ExportSymbol(MCSymbolData const &SymbolData, // For now, all non-variable symbols are exported, // the linker will sort the rest out for us. - return !SymbolData.getSymbol().isVariable(); + return SymbolData.isExternal() || !SymbolData.getSymbol().isVariable(); } bool WinCOFFObjectWriter::IsPhysicalSection(COFFSection *S) { @@ -632,13 +644,13 @@ void WinCOFFObjectWriter::RecordRelocation(const MCAssembler &Asm, MCSectionData const *SectionData = Fragment->getParent(); // Mark this symbol as requiring an entry in the symbol table. - assert(SectionMap.find(SectionData) != SectionMap.end() && + assert(SectionMap.find(&SectionData->getSection()) != SectionMap.end() && "Section must already have been defined in ExecutePostLayoutBinding!"); - assert(SymbolMap.find(&A_SD) != SymbolMap.end() && + assert(SymbolMap.find(&A_SD.getSymbol()) != SymbolMap.end() && "Symbol must already have been defined in ExecutePostLayoutBinding!"); - COFFSection *coff_section = SectionMap[SectionData]; - COFFSymbol *coff_symbol = SymbolMap[&A_SD]; + COFFSection *coff_section = SectionMap[&SectionData->getSection()]; + COFFSymbol *coff_symbol = SymbolMap[&A_SD.getSymbol()]; if (Target.getSymB()) { if (&Target.getSymA()->getSymbol().getSection() @@ -796,7 +808,7 @@ void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm, for (MCAssembler::const_iterator i = Asm.begin(), e = Asm.end(); i != e; i++) { - COFFSection *Sec = SectionMap[i]; + COFFSection *Sec = SectionMap[&i->getSection()]; if (Sec->Number == -1) continue; diff --git a/lib/MC/WinCOFFStreamer.cpp b/lib/MC/WinCOFFStreamer.cpp index 9fd80a4f63c..b270648cfc8 100644 --- a/lib/MC/WinCOFFStreamer.cpp +++ b/lib/MC/WinCOFFStreamer.cpp @@ -245,9 +245,11 @@ void WinCOFFStreamer::EmitSymbolAttribute(MCSymbol *Symbol, : true) && "Got non COFF section in the COFF backend!"); switch (Attribute) { case MCSA_WeakReference: - getAssembler().getOrCreateSymbolData(*Symbol).modifyFlags( - COFF::SF_WeakReference, - COFF::SF_WeakReference); + case MCSA_Weak: { + MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); + SD.modifyFlags(COFF::SF_WeakExternal, COFF::SF_WeakExternal); + SD.setExternal(true); + } break; case MCSA_Global: diff --git a/test/MC/COFF/weak.s b/test/MC/COFF/weak.s new file mode 100644 index 00000000000..d910059a47d --- /dev/null +++ b/test/MC/COFF/weak.s @@ -0,0 +1,51 @@ +// This tests that default-null weak symbols (a GNU extension) are created +// properly via the .weak directive. + +// RUN: llvm-mc -filetype=obj < %s | coff-dump.py | FileCheck %s + + .def _main; + .scl 2; + .type 32; + .endef + .text + .globl _main + .align 16, 0x90 +_main: # @main +# BB#0: # %entry + subl $4, %esp + movl $_test_weak, %eax + testl %eax, %eax + je LBB0_2 +# BB#1: # %if.then + calll _test_weak + movl $1, %eax + addl $4, %esp + ret +LBB0_2: # %return + xorl %eax, %eax + addl $4, %esp + ret + + .weak _test_weak + +// CHECK: Symbols = [ + +// CHECK: Name = _test_weak +// CHECK-NEXT: Value = 0 +// CHECK-NEXT: SectionNumber = 0 +// CHECK-NEXT: SimpleType = IMAGE_SYM_TYPE_NULL (0) +// CHECK-NEXT: ComplexType = IMAGE_SYM_DTYPE_NULL (0) +// CHECK-NEXT: StorageClass = IMAGE_SYM_CLASS_WEAK_EXTERNAL (105) +// CHECK-NEXT: NumberOfAuxSymbols = 1 +// CHECK-NEXT: AuxillaryData = +// CHECK-NEXT: 05 00 00 00 02 00 00 00 - 00 00 00 00 00 00 00 00 |................| +// CHECK-NEXT: 00 00 |..| + +// CHECK: Name = .weak._test_weak.default +// CHECK-NEXT: Value = 0 +// CHECK-NEXT: SectionNumber = 65535 +// CHECK-NEXT: SimpleType = IMAGE_SYM_TYPE_NULL (0) +// CHECK-NEXT: ComplexType = IMAGE_SYM_DTYPE_NULL (0) +// CHECK-NEXT: StorageClass = IMAGE_SYM_CLASS_EXTERNAL (2) +// CHECK-NEXT: NumberOfAuxSymbols = 0 +// CHECK-NEXT: AuxillaryData =