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

66
include/llvm/IR/Comdat.h Normal file
View File

@ -0,0 +1,66 @@
//===-- llvm/IR/Comdat.h - Comdat definitions -------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
/// @file
/// This file contains the declaration of the Comdat class, which represents a
/// single COMDAT in LLVM.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_IR_COMDAT_H
#define LLVM_IR_COMDAT_H
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Compiler.h"
namespace llvm {
class raw_ostream;
template <typename ValueTy> class StringMapEntry;
// This is a Name X SelectionKind pair. The reason for having this be an
// independent object instead of just adding the name and the SelectionKind
// to a GlobalObject is that it is invalid to have two Comdats with the same
// name but different SelectionKind. This structure makes that unrepresentable.
class Comdat {
public:
enum SelectionKind {
Any, ///< The linker may choose any COMDAT.
ExactMatch, ///< The data referenced by the COMDAT must be the same.
Largest, ///< The linker will choose the largest COMDAT.
NoDuplicates, ///< No other Module may specify this COMDAT.
SameSize, ///< The data referenced by the COMDAT must be the same size.
};
Comdat(Comdat &&C);
SelectionKind getSelectionKind() const { return SK; }
void setSelectionKind(SelectionKind Val) { SK = Val; }
StringRef getName() const;
void print(raw_ostream &OS) const;
void dump() const;
private:
friend class Module;
Comdat();
Comdat(SelectionKind SK, StringMapEntry<Comdat> *Name);
Comdat(const Comdat &) LLVM_DELETED_FUNCTION;
// Points to the map in Module.
StringMapEntry<Comdat> *Name;
SelectionKind SK;
};
inline raw_ostream &operator<<(raw_ostream &OS, const Comdat &C) {
C.print(OS);
return OS;
}
} // end llvm namespace
#endif

View File

@ -87,6 +87,21 @@ public:
return getOperand(0);
}
const GlobalObject *getBaseObject() const {
return const_cast<GlobalAlias *>(this)->getBaseObject();
}
GlobalObject *getBaseObject() {
return dyn_cast<GlobalObject>(getAliasee()->stripInBoundsOffsets());
}
const GlobalObject *getBaseObject(const DataLayout &DL, APInt &Offset) const {
return const_cast<GlobalAlias *>(this)->getBaseObject(DL, Offset);
}
GlobalObject *getBaseObject(const DataLayout &DL, APInt &Offset) {
return dyn_cast<GlobalObject>(
getAliasee()->stripAndAccumulateInBoundsConstantOffsets(DL, Offset));
}
static bool isValidLinkage(LinkageTypes L) {
return isExternalLinkage(L) || isLocalLinkage(L) ||
isWeakLinkage(L) || isLinkOnceLinkage(L);

View File

@ -20,7 +20,7 @@
#include "llvm/IR/GlobalValue.h"
namespace llvm {
class Comdat;
class Module;
class GlobalObject : public GlobalValue {
@ -29,11 +29,12 @@ class GlobalObject : public GlobalValue {
protected:
GlobalObject(Type *Ty, ValueTy VTy, Use *Ops, unsigned NumOps,
LinkageTypes Linkage, const Twine &Name)
: GlobalValue(Ty, VTy, Ops, NumOps, Linkage, Name) {
: GlobalValue(Ty, VTy, Ops, NumOps, Linkage, Name), ObjComdat(nullptr) {
setGlobalValueSubClassData(0);
}
std::string Section; // Section to emit this into, empty means default
Comdat *ObjComdat;
public:
unsigned getAlignment() const {
return (1u << getGlobalValueSubClassData()) >> 1;
@ -44,6 +45,11 @@ public:
const char *getSection() const { return Section.c_str(); }
void setSection(StringRef S);
bool hasComdat() const { return getComdat() != nullptr; }
const Comdat *getComdat() const { return ObjComdat; }
Comdat *getComdat() { return ObjComdat; }
void setComdat(Comdat *C) { ObjComdat = C; }
void copyAttributesFrom(const GlobalValue *Src) override;
// Methods for support type inquiry through isa, cast, and dyn_cast:

View File

@ -23,6 +23,7 @@
namespace llvm {
class Comdat;
class PointerType;
class Module;
@ -110,6 +111,12 @@ public:
bool hasUnnamedAddr() const { return UnnamedAddr; }
void setUnnamedAddr(bool Val) { UnnamedAddr = Val; }
bool hasComdat() const { return getComdat() != nullptr; }
Comdat *getComdat();
const Comdat *getComdat() const {
return const_cast<GlobalValue *>(this)->getComdat();
}
VisibilityTypes getVisibility() const { return VisibilityTypes(Visibility); }
bool hasDefaultVisibility() const { return Visibility == DefaultVisibility; }
bool hasHiddenVisibility() const { return Visibility == HiddenVisibility; }

View File

@ -16,6 +16,7 @@
#define LLVM_IR_MODULE_H
#include "llvm/ADT/iterator_range.h"
#include "llvm/IR/Comdat.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalAlias.h"
@ -123,6 +124,8 @@ public:
typedef iplist<GlobalAlias> AliasListType;
/// The type for the list of named metadata.
typedef ilist<NamedMDNode> NamedMDListType;
/// The type of the comdat "symbol" table.
typedef StringMap<Comdat> ComdatSymTabType;
/// The Global Variable iterator.
typedef GlobalListType::iterator global_iterator;
@ -197,6 +200,7 @@ private:
NamedMDListType NamedMDList; ///< The named metadata in the module
std::string GlobalScopeAsm; ///< Inline Asm at global scope.
ValueSymbolTable *ValSymTab; ///< Symbol table for values
ComdatSymTabType ComdatSymTab; ///< Symbol table for COMDATs
std::unique_ptr<GVMaterializer>
Materializer; ///< Used to materialize GlobalValues
std::string ModuleID; ///< Human readable identifier for the module
@ -403,6 +407,14 @@ public:
/// Remove the given NamedMDNode from this module and delete it.
void eraseNamedMetadata(NamedMDNode *NMD);
/// @}
/// @name Comdat Accessors
/// @{
/// Return the Comdat in the module with the specified name. It is created
/// if it didn't already exist.
Comdat *getOrInsertComdat(StringRef Name);
/// @}
/// @name Module Flags Accessors
/// @{
@ -504,6 +516,10 @@ public:
const ValueSymbolTable &getValueSymbolTable() const { return *ValSymTab; }
/// Get the Module's symbol table of global variable and function identifiers.
ValueSymbolTable &getValueSymbolTable() { return *ValSymTab; }
/// Get the Module's symbol table for COMDATs (constant).
const ComdatSymTabType &getComdatSymbolTable() const { return ComdatSymTab; }
/// Get the Module's symbol table for COMDATs.
ComdatSymTabType &getComdatSymbolTable() { return ComdatSymTab; }
/// @}
/// @name Global Variable Iteration