IR: Add COMDATs to the IR

This new IR facility allows us to represent the object-file semantic of
a COMDAT group.

COMDATs allow us to tie together sections and make the inclusion of one
dependent on another. This is required to implement features like MS
ABI VFTables and optimizing away certain kinds of initialization in C++.

This functionality is only representable in COFF and ELF, Mach-O has no
similar mechanism.

Differential Revision: http://reviews.llvm.org/D4178

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@211920 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
David Majnemer
2014-06-27 18:19:56 +00:00
parent 4a295dfbf9
commit c8a1169c93
56 changed files with 1511 additions and 104 deletions

View File

@ -524,6 +524,35 @@ static unsigned getEncodedThreadLocalMode(const GlobalValue &GV) {
llvm_unreachable("Invalid TLS model");
}
static unsigned getEncodedComdatSelectionKind(const Comdat &C) {
switch (C.getSelectionKind()) {
case Comdat::Any:
return bitc::COMDAT_SELECTION_KIND_ANY;
case Comdat::ExactMatch:
return bitc::COMDAT_SELECTION_KIND_EXACT_MATCH;
case Comdat::Largest:
return bitc::COMDAT_SELECTION_KIND_LARGEST;
case Comdat::NoDuplicates:
return bitc::COMDAT_SELECTION_KIND_NO_DUPLICATES;
case Comdat::SameSize:
return bitc::COMDAT_SELECTION_KIND_SAME_SIZE;
}
llvm_unreachable("Invalid selection kind");
}
static void writeComdats(const ValueEnumerator &VE, BitstreamWriter &Stream) {
SmallVector<uint8_t, 64> Vals;
for (const Comdat *C : VE.getComdats()) {
// COMDAT: [selection_kind, name]
Vals.push_back(getEncodedComdatSelectionKind(*C));
Vals.push_back(C->getName().size());
for (char Chr : C->getName())
Vals.push_back((unsigned char)Chr);
Stream.EmitRecord(bitc::MODULE_CODE_COMDAT, Vals, /*AbbrevToUse=*/0);
Vals.clear();
}
}
// Emit top-level description of module, including target triple, inline asm,
// descriptors for global variables, and function prototype info.
static void WriteModuleInfo(const Module *M, const ValueEnumerator &VE,
@ -625,12 +654,14 @@ static void WriteModuleInfo(const Module *M, const ValueEnumerator &VE,
if (GV.isThreadLocal() ||
GV.getVisibility() != GlobalValue::DefaultVisibility ||
GV.hasUnnamedAddr() || GV.isExternallyInitialized() ||
GV.getDLLStorageClass() != GlobalValue::DefaultStorageClass) {
GV.getDLLStorageClass() != GlobalValue::DefaultStorageClass ||
GV.hasComdat()) {
Vals.push_back(getEncodedVisibility(GV));
Vals.push_back(getEncodedThreadLocalMode(GV));
Vals.push_back(GV.hasUnnamedAddr());
Vals.push_back(GV.isExternallyInitialized());
Vals.push_back(getEncodedDLLStorageClass(GV));
Vals.push_back(GV.hasComdat() ? VE.getComdatID(GV.getComdat()) : 0);
} else {
AbbrevToUse = SimpleGVarAbbrev;
}
@ -656,6 +687,7 @@ static void WriteModuleInfo(const Module *M, const ValueEnumerator &VE,
Vals.push_back(F.hasPrefixData() ? (VE.getValueID(F.getPrefixData()) + 1)
: 0);
Vals.push_back(getEncodedDLLStorageClass(F));
Vals.push_back(F.hasComdat() ? VE.getComdatID(F.getComdat()) : 0);
unsigned AbbrevToUse = 0;
Stream.EmitRecord(bitc::MODULE_CODE_FUNCTION, Vals, AbbrevToUse);
@ -1915,6 +1947,8 @@ static void WriteModule(const Module *M, BitstreamWriter &Stream) {
// Emit information describing all of the types in the module.
WriteTypeTable(VE, Stream);
writeComdats(VE, Stream);
// Emit top-level description of module, including target triple, inline asm,
// descriptors for global variables, and function prototype info.
WriteModuleInfo(M, VE, Stream);

View File

@ -117,6 +117,12 @@ unsigned ValueEnumerator::getInstructionID(const Instruction *Inst) const {
return I->second;
}
unsigned ValueEnumerator::getComdatID(const Comdat *C) const {
unsigned ComdatID = Comdats.idFor(C);
assert(ComdatID && "Comdat not found!");
return ComdatID;
}
void ValueEnumerator::setInstructionID(const Instruction *I) {
InstructionMap[I] = InstructionCount++;
}
@ -307,6 +313,10 @@ void ValueEnumerator::EnumerateValue(const Value *V) {
return;
}
if (auto *GO = dyn_cast<GlobalObject>(V))
if (const Comdat *C = GO->getComdat())
Comdats.insert(C);
// Enumerate the type of this value.
EnumerateType(V->getType());

View File

@ -16,6 +16,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/UniqueVector.h"
#include "llvm/IR/Attributes.h"
#include <vector>
@ -25,6 +26,7 @@ class Type;
class Value;
class Instruction;
class BasicBlock;
class Comdat;
class Function;
class Module;
class MDNode;
@ -48,6 +50,10 @@ private:
typedef DenseMap<const Value*, unsigned> ValueMapType;
ValueMapType ValueMap;
ValueList Values;
typedef UniqueVector<const Comdat *> ComdatSetType;
ComdatSetType Comdats;
ValueList MDValues;
SmallVector<const MDNode *, 8> FunctionLocalMDs;
ValueMapType MDValueMap;
@ -139,6 +145,9 @@ public:
return AttributeGroups;
}
const ComdatSetType &getComdats() const { return Comdats; }
unsigned getComdatID(const Comdat *C) const;
/// getGlobalBasicBlockID - This returns the function-specific ID for the
/// specified basic block. This is relatively expensive information, so it
/// should only be used by rare constructs such as address-of-label.