mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-13 22:24:07 +00:00
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:
@ -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);
|
||||
|
@ -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());
|
||||
|
||||
|
@ -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.
|
||||
|
Reference in New Issue
Block a user