diff options
Diffstat (limited to 'lib/IR')
-rw-r--r-- | lib/IR/AsmWriter.cpp | 67 | ||||
-rw-r--r-- | lib/IR/AsmWriter.h | 4 | ||||
-rw-r--r-- | lib/IR/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib/IR/Comdat.cpp | 25 | ||||
-rw-r--r-- | lib/IR/Globals.cpp | 19 | ||||
-rw-r--r-- | lib/IR/Module.cpp | 8 | ||||
-rw-r--r-- | lib/IR/Verifier.cpp | 33 |
7 files changed, 148 insertions, 9 deletions
diff --git a/lib/IR/AsmWriter.cpp b/lib/IR/AsmWriter.cpp index 398e3d5f2a..87d26b164b 100644 --- a/lib/IR/AsmWriter.cpp +++ b/lib/IR/AsmWriter.cpp @@ -106,6 +106,7 @@ static void PrintEscapedString(StringRef Name, raw_ostream &Out) { enum PrefixType { GlobalPrefix, + ComdatPrefix, LabelPrefix, LocalPrefix, NoPrefix @@ -119,6 +120,7 @@ static void PrintLLVMName(raw_ostream &OS, StringRef Name, PrefixType Prefix) { switch (Prefix) { case NoPrefix: break; case GlobalPrefix: OS << '@'; break; + case ComdatPrefix: OS << '$'; break; case LabelPrefix: break; case LocalPrefix: OS << '%'; break; } @@ -1165,8 +1167,15 @@ static void WriteAsOperandInternal(raw_ostream &Out, const Value *V, } void AssemblyWriter::init() { - if (TheModule) - TypePrinter.incorporateTypes(*TheModule); + if (!TheModule) + return; + TypePrinter.incorporateTypes(*TheModule); + for (const Function &F : *TheModule) + if (const Comdat *C = F.getComdat()) + Comdats.insert(C); + for (const GlobalVariable &GV : TheModule->globals()) + if (const Comdat *C = GV.getComdat()) + Comdats.insert(C); } @@ -1308,6 +1317,15 @@ void AssemblyWriter::printModule(const Module *M) { printTypeIdentities(); + // Output all comdats. + if (!Comdats.empty()) + Out << '\n'; + for (const Comdat *C : Comdats) { + printComdat(C); + if (C != Comdats.back()) + Out << '\n'; + } + // Output all globals. if (!M->global_empty()) Out << '\n'; for (Module::const_global_iterator I = M->global_begin(), E = M->global_end(); @@ -1470,6 +1488,10 @@ void AssemblyWriter::printGlobal(const GlobalVariable *GV) { PrintEscapedString(GV->getSection(), Out); Out << '"'; } + if (GV->hasComdat()) { + Out << ", comdat "; + PrintLLVMName(Out, GV->getComdat()->getName(), ComdatPrefix); + } if (GV->getAlignment()) Out << ", align " << GV->getAlignment(); @@ -1506,10 +1528,19 @@ void AssemblyWriter::printAlias(const GlobalAlias *GA) { writeOperand(Aliasee, !isa<ConstantExpr>(Aliasee)); } + if (GA->hasComdat()) { + Out << ", comdat "; + PrintLLVMName(Out, GA->getComdat()->getName(), ComdatPrefix); + } + printInfoComment(*GA); Out << '\n'; } +void AssemblyWriter::printComdat(const Comdat *C) { + C->print(Out); +} + void AssemblyWriter::printTypeIdentities() { if (TypePrinter.NumberedTypes.empty() && TypePrinter.NamedTypes.empty()) @@ -1647,6 +1678,10 @@ void AssemblyWriter::printFunction(const Function *F) { PrintEscapedString(F->getSection(), Out); Out << '"'; } + if (F->hasComdat()) { + Out << " comdat "; + PrintLLVMName(Out, F->getComdat()->getName(), ComdatPrefix); + } if (F->getAlignment()) Out << " align " << F->getAlignment(); if (F->hasGC()) @@ -2158,6 +2193,31 @@ void NamedMDNode::print(raw_ostream &ROS) const { W.printNamedMDNode(this); } +void Comdat::print(raw_ostream &ROS) const { + PrintLLVMName(ROS, getName(), ComdatPrefix); + ROS << " = comdat "; + + switch (getSelectionKind()) { + case Comdat::Any: + ROS << "any"; + break; + case Comdat::ExactMatch: + ROS << "exactmatch"; + break; + case Comdat::Largest: + ROS << "largest"; + break; + case Comdat::NoDuplicates: + ROS << "noduplicates"; + break; + case Comdat::SameSize: + ROS << "samesize"; + break; + } + + ROS << '\n'; +} + void Type::print(raw_ostream &OS) const { TypePrinting TP; TP.print(const_cast<Type*>(this), OS); @@ -2241,5 +2301,8 @@ void Type::dump() const { print(dbgs()); } // Module::dump() - Allow printing of Modules from the debugger. void Module::dump() const { print(dbgs(), nullptr); } +// \brief Allow printing of Comdats from the debugger. +void Comdat::dump() const { print(dbgs()); } + // NamedMDNode::dump() - Allow printing of NamedMDNodes from the debugger. void NamedMDNode::dump() const { print(dbgs()); } diff --git a/lib/IR/AsmWriter.h b/lib/IR/AsmWriter.h index b4ce6de10d..aef9c8a3e9 100644 --- a/lib/IR/AsmWriter.h +++ b/lib/IR/AsmWriter.h @@ -16,6 +16,7 @@ #define LLVM_IR_ASSEMBLYWRITER_H #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SetVector.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/TypeFinder.h" @@ -26,6 +27,7 @@ namespace llvm { class BasicBlock; class Function; class GlobalValue; +class Comdat; class Module; class NamedMDNode; class Value; @@ -70,6 +72,7 @@ private: SlotTracker &Machine; TypePrinting TypePrinter; AssemblyAnnotationWriter *AnnotationWriter; + SetVector<const Comdat *> Comdats; public: /// Construct an AssemblyWriter with an external SlotTracker @@ -101,6 +104,7 @@ public: void printTypeIdentities(); void printGlobal(const GlobalVariable *GV); void printAlias(const GlobalAlias *GV); + void printComdat(const Comdat *C); void printFunction(const Function *F); void printArgument(const Argument *FA, AttributeSet Attrs, unsigned Idx); void printBasicBlock(const BasicBlock *BB); diff --git a/lib/IR/CMakeLists.txt b/lib/IR/CMakeLists.txt index b027ae5f50..38a80b18bd 100644 --- a/lib/IR/CMakeLists.txt +++ b/lib/IR/CMakeLists.txt @@ -3,6 +3,7 @@ add_llvm_library(LLVMCore Attributes.cpp AutoUpgrade.cpp BasicBlock.cpp + Comdat.cpp ConstantFold.cpp ConstantRange.cpp Constants.cpp diff --git a/lib/IR/Comdat.cpp b/lib/IR/Comdat.cpp new file mode 100644 index 0000000000..80715ff40b --- /dev/null +++ b/lib/IR/Comdat.cpp @@ -0,0 +1,25 @@ +//===-- Comdat.cpp - Implement Metadata classes --------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the Comdat class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/IR/Comdat.h" +#include "llvm/ADT/StringMap.h" +using namespace llvm; + +Comdat::Comdat(SelectionKind SK, StringMapEntry<Comdat> *Name) + : Name(Name), SK(SK) {} + +Comdat::Comdat(Comdat &&C) : Name(C.Name), SK(C.SK) {} + +Comdat::Comdat() : Name(nullptr), SK(Comdat::Any) {} + +StringRef Comdat::getName() const { return Name->first(); } diff --git a/lib/IR/Globals.cpp b/lib/IR/Globals.cpp index 5410cc031d..244e3e4bae 100644 --- a/lib/IR/Globals.cpp +++ b/lib/IR/Globals.cpp @@ -59,15 +59,10 @@ void GlobalValue::copyAttributesFrom(const GlobalValue *Src) { setDLLStorageClass(Src->getDLLStorageClass()); } -static const GlobalObject *getBaseObject(const Constant &C) { - // FIXME: We should probably return a base + offset pair for non-zero GEPs. - return dyn_cast<GlobalObject>(C.stripPointerCasts()); -} - unsigned GlobalValue::getAlignment() const { if (auto *GA = dyn_cast<GlobalAlias>(this)) { // In general we cannot compute this at the IR level, but we try. - if (const GlobalObject *GO = getBaseObject(*GA->getAliasee())) + if (const GlobalObject *GO = GA->getBaseObject()) return GO->getAlignment(); // FIXME: we should also be able to handle: @@ -96,13 +91,23 @@ void GlobalObject::copyAttributesFrom(const GlobalValue *Src) { const char *GlobalValue::getSection() const { if (auto *GA = dyn_cast<GlobalAlias>(this)) { // In general we cannot compute this at the IR level, but we try. - if (const GlobalObject *GO = getBaseObject(*GA->getAliasee())) + if (const GlobalObject *GO = GA->getBaseObject()) return GO->getSection(); return ""; } return cast<GlobalObject>(this)->getSection(); } +Comdat *GlobalValue::getComdat() { + if (auto *GA = dyn_cast<GlobalAlias>(this)) { + // In general we cannot compute this at the IR level, but we try. + if (const GlobalObject *GO = GA->getBaseObject()) + return const_cast<GlobalObject *>(GO)->getComdat(); + return nullptr; + } + return cast<GlobalObject>(this)->getComdat(); +} + void GlobalObject::setSection(StringRef S) { Section = S; } bool GlobalValue::isDeclaration() const { diff --git a/lib/IR/Module.cpp b/lib/IR/Module.cpp index 9889f00974..d853bf4cfa 100644 --- a/lib/IR/Module.cpp +++ b/lib/IR/Module.cpp @@ -453,3 +453,11 @@ unsigned Module::getDwarfVersion() const { return dwarf::DWARF_VERSION; return cast<ConstantInt>(Val)->getZExtValue(); } + +Comdat *Module::getOrInsertComdat(StringRef Name) { + Comdat C; + StringMapEntry<Comdat> &Entry = + ComdatSymTab.GetOrCreateValue(Name, std::move(C)); + Entry.second.Name = &Entry; + return &Entry.second; +} diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp index ad3c29c564..24f3acb995 100644 --- a/lib/IR/Verifier.cpp +++ b/lib/IR/Verifier.cpp @@ -107,6 +107,12 @@ struct VerifierSupport { OS << ' ' << *T; } + void WriteComdat(const Comdat *C) { + if (!C) + return; + OS << *C; + } + // CheckFailed - A check failed, so print out the condition and the message // that failed. This provides a nice place to put a breakpoint if you want // to see why something is not correct. @@ -138,6 +144,12 @@ struct VerifierSupport { WriteType(T3); Broken = true; } + + void CheckFailed(const Twine &Message, const Comdat *C) { + OS << Message.str() << "\n"; + WriteComdat(C); + Broken = true; + } }; class Verifier : public InstVisitor<Verifier>, VerifierSupport { friend class InstVisitor<Verifier>; @@ -230,6 +242,9 @@ public: I != E; ++I) visitNamedMDNode(*I); + for (const StringMapEntry<Comdat> &SMEC : M.getComdatSymbolTable()) + visitComdat(SMEC.getValue()); + visitModuleFlags(M); visitModuleIdents(M); @@ -246,6 +261,7 @@ private: const GlobalAlias &A, const Constant &C); void visitNamedMDNode(const NamedMDNode &NMD); void visitMDNode(MDNode &MD, Function *F); + void visitComdat(const Comdat &C); void visitModuleIdents(const Module &M); void visitModuleFlags(const Module &M); void visitModuleFlag(const MDNode *Op, @@ -387,6 +403,7 @@ void Verifier::visitGlobalVariable(const GlobalVariable &GV) { "'common' global must have a zero initializer!", &GV); Assert1(!GV.isConstant(), "'common' global may not be marked constant!", &GV); + Assert1(!GV.hasComdat(), "'common' global may not be in a Comdat!", &GV); } } else { Assert1(GV.hasExternalLinkage() || GV.hasExternalWeakLinkage(), @@ -578,6 +595,22 @@ void Verifier::visitMDNode(MDNode &MD, Function *F) { } } +void Verifier::visitComdat(const Comdat &C) { + // All Comdat::SelectionKind values other than Comdat::Any require a + // GlobalValue with the same name as the Comdat. + const GlobalValue *GV = M->getNamedValue(C.getName()); + if (C.getSelectionKind() != Comdat::Any) + Assert1(GV, + "comdat selection kind requires a global value with the same name", + &C); + // The Module is invalid if the GlobalValue has local linkage. Allowing + // otherwise opens us up to seeing the underling global value get renamed if + // collisions occur. + if (GV) + Assert1(!GV->hasLocalLinkage(), "comdat global value has local linkage", + GV); +} + void Verifier::visitModuleIdents(const Module &M) { const NamedMDNode *Idents = M.getNamedMetadata("llvm.ident"); if (!Idents) |