From ca271dd4263fd74bb3613ef1988ae50b59531edb Mon Sep 17 00:00:00 2001 From: Anton Korobeynikov Date: Wed, 9 Jul 2008 13:19:38 +0000 Subject: [PATCH] Properly handle linkonce stuff llvm-svn: 53296 --- include/llvm/Target/TargetAsmInfo.h | 8 +- lib/Target/TargetAsmInfo.cpp | 23 ++++++ lib/Target/X86/X86TargetAsmInfo.cpp | 112 ++++++++++++++++++++-------- lib/Target/X86/X86TargetAsmInfo.h | 2 + 4 files changed, 110 insertions(+), 35 deletions(-) diff --git a/include/llvm/Target/TargetAsmInfo.h b/include/llvm/Target/TargetAsmInfo.h index a36ce476028..13b32e790ed 100644 --- a/include/llvm/Target/TargetAsmInfo.h +++ b/include/llvm/Target/TargetAsmInfo.h @@ -56,11 +56,6 @@ namespace llvm { }; } - struct SectionInfo { - SectionKind::Kind kind; - SectionFlags::Flags flags; - }; - class TargetMachine; class CallInst; class GlobalValue; @@ -476,6 +471,9 @@ namespace llvm { /// global with all necessary flags and marks. virtual std::string SectionForGlobal(const GlobalValue *GV) const; + virtual std::string UniqueSectionForGlobal(const GlobalValue* GV, + SectionKind::Kind kind) const; + // Accessors. // const char *getTextSection() const { diff --git a/lib/Target/TargetAsmInfo.cpp b/lib/Target/TargetAsmInfo.cpp index 923cac6640c..6967ebe4860 100644 --- a/lib/Target/TargetAsmInfo.cpp +++ b/lib/Target/TargetAsmInfo.cpp @@ -266,3 +266,26 @@ TargetAsmInfo::SectionForGlobal(const GlobalValue *GV) const { return getDataSection(); } + +std::string +TargetAsmInfo::UniqueSectionForGlobal(const GlobalValue* GV, + SectionKind::Kind kind) const { + switch (kind) { + case SectionKind::Text: + return ".llvm.linkonce.t." + GV->getName(); + case SectionKind::Data: + return ".llvm.linkonce.d." + GV->getName(); + case SectionKind::BSS: + return ".llvm.linkonce.b." + GV->getName(); + case SectionKind::ROData: + case SectionKind::RODataMergeConst: + case SectionKind::RODataMergeStr: + return ".llvm.linkonce.r." + GV->getName(); + case SectionKind::ThreadData: + return ".llvm.linkonce.td." + GV->getName(); + case SectionKind::ThreadBSS: + return ".llvm.linkonce.tb." + GV->getName(); + default: + assert(0 && "Unknown section kind"); + } +} diff --git a/lib/Target/X86/X86TargetAsmInfo.cpp b/lib/Target/X86/X86TargetAsmInfo.cpp index 750e6b36bc2..80156c79c03 100644 --- a/lib/Target/X86/X86TargetAsmInfo.cpp +++ b/lib/Target/X86/X86TargetAsmInfo.cpp @@ -375,6 +375,41 @@ unsigned X86TargetAsmInfo::PreferredEHDataFormat(DwarfEncoding::Target Reason, } } +std::string X86TargetAsmInfo::UniqueSectionForGlobal(const GlobalValue* GV, + SectionKind::Kind kind) const { + const X86Subtarget *Subtarget = &X86TM->getSubtarget(); + + switch (Subtarget->TargetType) { + case X86Subtarget::isDarwin: + if (kind == SectionKind::Text) + return "__TEXT,__textcoal_nt,coalesced,pure_instructions"; + else + return "__DATA,__datacoal_nt,coalesced"; + case X86Subtarget::isCygwin: + case X86Subtarget::isMingw: + switch (kind) { + case SectionKind::Text: + return ".text$linkonce" + GV->getName(); + case SectionKind::Data: + case SectionKind::BSS: + case SectionKind::ThreadData: + case SectionKind::ThreadBSS: + return ".data$linkonce" + GV->getName(); + case SectionKind::ROData: + case SectionKind::RODataMergeConst: + case SectionKind::RODataMergeStr: + return ".rdata$linkonce" + GV->getName(); + default: + assert(0 && "Unknown section kind"); + } + case X86Subtarget::isELF: + return TargetAsmInfo::UniqueSectionForGlobal(GV, kind); + default: + return ""; + } +} + + std::string X86TargetAsmInfo::SectionForGlobal(const GlobalValue *GV) const { const X86Subtarget *Subtarget = &X86TM->getSubtarget(); SectionKind::Kind kind = SectionKindForGlobal(GV); @@ -383,41 +418,58 @@ std::string X86TargetAsmInfo::SectionForGlobal(const GlobalValue *GV) const { // FIXME: Should we use some hashing based on section name and just check // flags? + // FIXME: It seems, that Darwin uses much more sections. // Select section name - if (const Function *F = dyn_cast(GV)) { - // Implement here - } else if (const GlobalVariable *GVar = dyn_cast(GV)) { - if (GVar->hasSection()) { - // Honour section already set, if any - Name = GVar->getSection(); - } else { - // Use default section depending on the 'type' of global - // FIXME: Handle linkonce stuff - switch (kind) { - case SectionKind::Data: - Name = DataSection; + if (GV->hasSection()) { + // Honour section already set, if any + Name = GV->getSection(); + } else { + // Use default section depending on the 'type' of global + if (const Function *F = dyn_cast(GV)) { + switch (F->getLinkage()) { + default: assert(0 && "Unknown linkage type!"); + case Function::InternalLinkage: + case Function::DLLExportLinkage: + case Function::ExternalLinkage: + Name = TextSection; break; - case SectionKind::BSS: - Name = (BSSSection ? BSSSection : DataSection); + case Function::WeakLinkage: + case Function::LinkOnceLinkage: + Name = UniqueSectionForGlobal(F, kind); break; - case SectionKind::ROData: - case SectionKind::RODataMergeStr: - case SectionKind::RODataMergeConst: - // FIXME: Temporary - Name = DataSection; - break; - case SectionKind::ThreadData: - Name = (TLSDataSection ? TLSDataSection : DataSection); - break; - case SectionKind::ThreadBSS: - Name = (TLSBSSSection ? TLSBSSSection : DataSection); - default: - assert(0 && "Unsuported section kind for global"); } - } - } else - assert(0 && "Unsupported global"); + } else if (const GlobalVariable *GVar = dyn_cast(GV)) { + if (GVar->hasCommonLinkage() || + GVar->hasLinkOnceLinkage() || + GVar->hasWeakLinkage()) + Name = UniqueSectionForGlobal(GVar, kind); + else { + switch (kind) { + case SectionKind::Data: + Name = DataSection; + break; + case SectionKind::BSS: + Name = (BSSSection ? BSSSection : DataSection); + break; + case SectionKind::ROData: + case SectionKind::RODataMergeStr: + case SectionKind::RODataMergeConst: + // FIXME: Temporary + Name = DataSection; + break; + case SectionKind::ThreadData: + Name = (TLSDataSection ? TLSDataSection : DataSection); + break; + case SectionKind::ThreadBSS: + Name = (TLSBSSSection ? TLSBSSSection : DataSection); + default: + assert(0 && "Unsuported section kind for global"); + } + } + } else + assert(0 && "Unsupported global"); + } // Add all special flags, etc switch (Subtarget->TargetType) { diff --git a/lib/Target/X86/X86TargetAsmInfo.h b/lib/Target/X86/X86TargetAsmInfo.h index 7d92c799bda..9f9ef3e9af4 100644 --- a/lib/Target/X86/X86TargetAsmInfo.h +++ b/lib/Target/X86/X86TargetAsmInfo.h @@ -28,6 +28,8 @@ namespace llvm { virtual unsigned PreferredEHDataFormat(DwarfEncoding::Target Reason, bool Global) const; virtual std::string SectionForGlobal(const GlobalValue *GV) const; + virtual std::string UniqueSectionForGlobal(const GlobalValue* GV, + SectionKind::Kind kind) const; private: const X86TargetMachine* X86TM;