mirror of
https://github.com/llvm/llvm-project.git
synced 2025-05-03 16:06:06 +00:00

Currently, opaque pointers are supported in two forms: The -force-opaque-pointers mode, where all pointers are opaque and typed pointers do not exist. And as a simple ptr type that can coexist with typed pointers. This patch removes support for the mixed mode. You either get typed pointers, or you get opaque pointers, but not both. In the (current) default mode, using ptr is forbidden. In -opaque-pointers mode, all pointers are opaque. The motivation here is that the mixed mode introduces additional issues that don't exist in fully opaque mode. D105155 is an example of a design problem. Looking at D109259, it would probably need additional work to support mixed mode (e.g. to generate GEPs for typed base but opaque result). Mixed mode will also end up inserting many casts between i8* and ptr, which would require significant additional work to consistently avoid. I don't think the mixed mode is particularly valuable, as it doesn't align with our end goal. The only thing I've found it to be moderately useful for is adding some opaque pointer tests in between typed pointer tests, but I think we can live without that. Differential Revision: https://reviews.llvm.org/D109290
236 lines
7.7 KiB
C++
236 lines
7.7 KiB
C++
//===- LLVMContextImpl.cpp - Implement LLVMContextImpl --------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file implements the opaque LLVMContextImpl.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "LLVMContextImpl.h"
|
|
#include "llvm/ADT/SetVector.h"
|
|
#include "llvm/IR/Module.h"
|
|
#include "llvm/IR/OptBisect.h"
|
|
#include "llvm/IR/Type.h"
|
|
#include "llvm/Support/CommandLine.h"
|
|
#include "llvm/Support/ManagedStatic.h"
|
|
#include <cassert>
|
|
#include <utility>
|
|
|
|
using namespace llvm;
|
|
|
|
static cl::opt<bool>
|
|
OpaquePointersCL("opaque-pointers", cl::desc("Use opaque pointers"),
|
|
cl::init(false));
|
|
|
|
LLVMContextImpl::LLVMContextImpl(LLVMContext &C)
|
|
: DiagHandler(std::make_unique<DiagnosticHandler>()),
|
|
VoidTy(C, Type::VoidTyID), LabelTy(C, Type::LabelTyID),
|
|
HalfTy(C, Type::HalfTyID), BFloatTy(C, Type::BFloatTyID),
|
|
FloatTy(C, Type::FloatTyID), DoubleTy(C, Type::DoubleTyID),
|
|
MetadataTy(C, Type::MetadataTyID), TokenTy(C, Type::TokenTyID),
|
|
X86_FP80Ty(C, Type::X86_FP80TyID), FP128Ty(C, Type::FP128TyID),
|
|
PPC_FP128Ty(C, Type::PPC_FP128TyID), X86_MMXTy(C, Type::X86_MMXTyID),
|
|
X86_AMXTy(C, Type::X86_AMXTyID), Int1Ty(C, 1), Int8Ty(C, 8),
|
|
Int16Ty(C, 16), Int32Ty(C, 32), Int64Ty(C, 64), Int128Ty(C, 128),
|
|
OpaquePointers(OpaquePointersCL) {}
|
|
|
|
LLVMContextImpl::~LLVMContextImpl() {
|
|
// NOTE: We need to delete the contents of OwnedModules, but Module's dtor
|
|
// will call LLVMContextImpl::removeModule, thus invalidating iterators into
|
|
// the container. Avoid iterators during this operation:
|
|
while (!OwnedModules.empty())
|
|
delete *OwnedModules.begin();
|
|
|
|
#ifndef NDEBUG
|
|
// Check for metadata references from leaked Values.
|
|
for (auto &Pair : ValueMetadata)
|
|
Pair.first->dump();
|
|
assert(ValueMetadata.empty() && "Values with metadata have been leaked");
|
|
#endif
|
|
|
|
// Drop references for MDNodes. Do this before Values get deleted to avoid
|
|
// unnecessary RAUW when nodes are still unresolved.
|
|
for (auto *I : DistinctMDNodes) {
|
|
// We may have DIArgList that were uniqued, and as it has a custom
|
|
// implementation of dropAllReferences, it needs to be explicitly invoked.
|
|
if (auto *AL = dyn_cast<DIArgList>(I)) {
|
|
AL->dropAllReferences();
|
|
continue;
|
|
}
|
|
I->dropAllReferences();
|
|
}
|
|
#define HANDLE_MDNODE_LEAF_UNIQUABLE(CLASS) \
|
|
for (auto *I : CLASS##s) \
|
|
I->dropAllReferences();
|
|
#include "llvm/IR/Metadata.def"
|
|
|
|
// Also drop references that come from the Value bridges.
|
|
for (auto &Pair : ValuesAsMetadata)
|
|
Pair.second->dropUsers();
|
|
for (auto &Pair : MetadataAsValues)
|
|
Pair.second->dropUse();
|
|
|
|
// Destroy MDNodes.
|
|
for (MDNode *I : DistinctMDNodes)
|
|
I->deleteAsSubclass();
|
|
#define HANDLE_MDNODE_LEAF_UNIQUABLE(CLASS) \
|
|
for (CLASS * I : CLASS##s) \
|
|
delete I;
|
|
#include "llvm/IR/Metadata.def"
|
|
|
|
// Free the constants.
|
|
for (auto *I : ExprConstants)
|
|
I->dropAllReferences();
|
|
for (auto *I : ArrayConstants)
|
|
I->dropAllReferences();
|
|
for (auto *I : StructConstants)
|
|
I->dropAllReferences();
|
|
for (auto *I : VectorConstants)
|
|
I->dropAllReferences();
|
|
ExprConstants.freeConstants();
|
|
ArrayConstants.freeConstants();
|
|
StructConstants.freeConstants();
|
|
VectorConstants.freeConstants();
|
|
InlineAsms.freeConstants();
|
|
|
|
CAZConstants.clear();
|
|
CPNConstants.clear();
|
|
UVConstants.clear();
|
|
PVConstants.clear();
|
|
IntConstants.clear();
|
|
FPConstants.clear();
|
|
CDSConstants.clear();
|
|
|
|
// Destroy attribute node lists.
|
|
for (FoldingSetIterator<AttributeSetNode> I = AttrsSetNodes.begin(),
|
|
E = AttrsSetNodes.end(); I != E; ) {
|
|
FoldingSetIterator<AttributeSetNode> Elem = I++;
|
|
delete &*Elem;
|
|
}
|
|
|
|
// Destroy MetadataAsValues.
|
|
{
|
|
SmallVector<MetadataAsValue *, 8> MDVs;
|
|
MDVs.reserve(MetadataAsValues.size());
|
|
for (auto &Pair : MetadataAsValues)
|
|
MDVs.push_back(Pair.second);
|
|
MetadataAsValues.clear();
|
|
for (auto *V : MDVs)
|
|
delete V;
|
|
}
|
|
|
|
// Destroy ValuesAsMetadata.
|
|
for (auto &Pair : ValuesAsMetadata)
|
|
delete Pair.second;
|
|
}
|
|
|
|
void LLVMContextImpl::dropTriviallyDeadConstantArrays() {
|
|
SmallSetVector<ConstantArray *, 4> WorkList;
|
|
|
|
// When ArrayConstants are of substantial size and only a few in them are
|
|
// dead, starting WorkList with all elements of ArrayConstants can be
|
|
// wasteful. Instead, starting WorkList with only elements that have empty
|
|
// uses.
|
|
for (ConstantArray *C : ArrayConstants)
|
|
if (C->use_empty())
|
|
WorkList.insert(C);
|
|
|
|
while (!WorkList.empty()) {
|
|
ConstantArray *C = WorkList.pop_back_val();
|
|
if (C->use_empty()) {
|
|
for (const Use &Op : C->operands()) {
|
|
if (auto *COp = dyn_cast<ConstantArray>(Op))
|
|
WorkList.insert(COp);
|
|
}
|
|
C->destroyConstant();
|
|
}
|
|
}
|
|
}
|
|
|
|
void Module::dropTriviallyDeadConstantArrays() {
|
|
Context.pImpl->dropTriviallyDeadConstantArrays();
|
|
}
|
|
|
|
namespace llvm {
|
|
|
|
/// Make MDOperand transparent for hashing.
|
|
///
|
|
/// This overload of an implementation detail of the hashing library makes
|
|
/// MDOperand hash to the same value as a \a Metadata pointer.
|
|
///
|
|
/// Note that overloading \a hash_value() as follows:
|
|
///
|
|
/// \code
|
|
/// size_t hash_value(const MDOperand &X) { return hash_value(X.get()); }
|
|
/// \endcode
|
|
///
|
|
/// does not cause MDOperand to be transparent. In particular, a bare pointer
|
|
/// doesn't get hashed before it's combined, whereas \a MDOperand would.
|
|
static const Metadata *get_hashable_data(const MDOperand &X) { return X.get(); }
|
|
|
|
} // end namespace llvm
|
|
|
|
unsigned MDNodeOpsKey::calculateHash(MDNode *N, unsigned Offset) {
|
|
unsigned Hash = hash_combine_range(N->op_begin() + Offset, N->op_end());
|
|
#ifndef NDEBUG
|
|
{
|
|
SmallVector<Metadata *, 8> MDs(drop_begin(N->operands(), Offset));
|
|
unsigned RawHash = calculateHash(MDs);
|
|
assert(Hash == RawHash &&
|
|
"Expected hash of MDOperand to equal hash of Metadata*");
|
|
}
|
|
#endif
|
|
return Hash;
|
|
}
|
|
|
|
unsigned MDNodeOpsKey::calculateHash(ArrayRef<Metadata *> Ops) {
|
|
return hash_combine_range(Ops.begin(), Ops.end());
|
|
}
|
|
|
|
StringMapEntry<uint32_t> *LLVMContextImpl::getOrInsertBundleTag(StringRef Tag) {
|
|
uint32_t NewIdx = BundleTagCache.size();
|
|
return &*(BundleTagCache.insert(std::make_pair(Tag, NewIdx)).first);
|
|
}
|
|
|
|
void LLVMContextImpl::getOperandBundleTags(SmallVectorImpl<StringRef> &Tags) const {
|
|
Tags.resize(BundleTagCache.size());
|
|
for (const auto &T : BundleTagCache)
|
|
Tags[T.second] = T.first();
|
|
}
|
|
|
|
uint32_t LLVMContextImpl::getOperandBundleTagID(StringRef Tag) const {
|
|
auto I = BundleTagCache.find(Tag);
|
|
assert(I != BundleTagCache.end() && "Unknown tag!");
|
|
return I->second;
|
|
}
|
|
|
|
SyncScope::ID LLVMContextImpl::getOrInsertSyncScopeID(StringRef SSN) {
|
|
auto NewSSID = SSC.size();
|
|
assert(NewSSID < std::numeric_limits<SyncScope::ID>::max() &&
|
|
"Hit the maximum number of synchronization scopes allowed!");
|
|
return SSC.insert(std::make_pair(SSN, SyncScope::ID(NewSSID))).first->second;
|
|
}
|
|
|
|
void LLVMContextImpl::getSyncScopeNames(
|
|
SmallVectorImpl<StringRef> &SSNs) const {
|
|
SSNs.resize(SSC.size());
|
|
for (const auto &SSE : SSC)
|
|
SSNs[SSE.second] = SSE.first();
|
|
}
|
|
|
|
/// Gets the OptPassGate for this LLVMContextImpl, which defaults to the
|
|
/// singleton OptBisect if not explicitly set.
|
|
OptPassGate &LLVMContextImpl::getOptPassGate() const {
|
|
if (!OPG)
|
|
OPG = &(*OptBisector);
|
|
return *OPG;
|
|
}
|
|
|
|
void LLVMContextImpl::setOptPassGate(OptPassGate& OPG) {
|
|
this->OPG = &OPG;
|
|
}
|