LowerTypeTests: Create LowerTypeTestsModule class and move implementation there. Related simplifications.

llvm-svn: 282455
This commit is contained in:
Peter Collingbourne 2016-09-26 23:54:39 +00:00
parent 52f97afa1b
commit de758baa03

View File

@ -208,26 +208,22 @@ struct ByteArrayInfo {
Constant *Mask;
};
struct LowerTypeTests : public ModulePass {
static char ID;
LowerTypeTests() : ModulePass(ID) {
initializeLowerTypeTestsPass(*PassRegistry::getPassRegistry());
}
Module *M;
class LowerTypeTestsModule {
Module &M;
bool LinkerSubsectionsViaSymbols;
Triple::ArchType Arch;
Triple::ObjectFormatType ObjectFormat;
IntegerType *Int1Ty;
IntegerType *Int8Ty;
IntegerType *Int32Ty;
Type *Int32PtrTy;
IntegerType *Int64Ty;
IntegerType *IntPtrTy;
IntegerType *Int1Ty = Type::getInt1Ty(M.getContext());
IntegerType *Int8Ty = Type::getInt8Ty(M.getContext());
IntegerType *Int32Ty = Type::getInt32Ty(M.getContext());
PointerType *Int32PtrTy = PointerType::getUnqual(Int32Ty);
IntegerType *Int64Ty = Type::getInt64Ty(M.getContext());
IntegerType *IntPtrTy = M.getDataLayout().getIntPtrType(M.getContext(), 0);
// Indirect function call index assignment counter for WebAssembly
uint64_t IndirectIndex;
uint64_t IndirectIndex = 1;
// Mapping from type identifiers to the call sites that test them.
DenseMap<Metadata *, std::vector<CallInst *>> TypeTestCallSites;
@ -263,8 +259,23 @@ struct LowerTypeTests : public ModulePass {
ArrayRef<Function *> Functions);
void buildBitSetsFromDisjointSet(ArrayRef<Metadata *> TypeIds,
ArrayRef<GlobalObject *> Globals);
public:
LowerTypeTestsModule(Module &M);
bool lower();
bool runOnModule(Module &M) override;
};
struct LowerTypeTests : public ModulePass {
static char ID;
LowerTypeTests() : ModulePass(ID) {
initializeLowerTypeTestsPass(*PassRegistry::getPassRegistry());
}
bool runOnModule(Module &M) override {
if (skipModule(M))
return false;
return LowerTypeTestsModule(M).lower();
}
};
} // anonymous namespace
@ -277,7 +288,7 @@ ModulePass *llvm::createLowerTypeTestsPass() { return new LowerTypeTests; }
/// Build a bit set for TypeId using the object layouts in
/// GlobalLayout.
BitSetInfo LowerTypeTests::buildBitSet(
BitSetInfo LowerTypeTestsModule::buildBitSet(
Metadata *TypeId, const DenseMap<GlobalObject *, uint64_t> &GlobalLayout) {
BitSetBuilder BSB;
@ -316,13 +327,13 @@ static Value *createMaskedBitTest(IRBuilder<> &B, Value *Bits,
return B.CreateICmpNE(MaskedBits, ConstantInt::get(BitsType, 0));
}
ByteArrayInfo *LowerTypeTests::createByteArray(BitSetInfo &BSI) {
ByteArrayInfo *LowerTypeTestsModule::createByteArray(BitSetInfo &BSI) {
// Create globals to stand in for byte arrays and masks. These never actually
// get initialized, we RAUW and erase them later in allocateByteArrays() once
// we know the offset and mask to use.
auto ByteArrayGlobal = new GlobalVariable(
*M, Int8Ty, /*isConstant=*/true, GlobalValue::PrivateLinkage, nullptr);
auto MaskGlobal = new GlobalVariable(*M, Int8Ty, /*isConstant=*/true,
M, Int8Ty, /*isConstant=*/true, GlobalValue::PrivateLinkage, nullptr);
auto MaskGlobal = new GlobalVariable(M, Int8Ty, /*isConstant=*/true,
GlobalValue::PrivateLinkage, nullptr);
ByteArrayInfos.emplace_back();
@ -335,7 +346,7 @@ ByteArrayInfo *LowerTypeTests::createByteArray(BitSetInfo &BSI) {
return BAI;
}
void LowerTypeTests::allocateByteArrays() {
void LowerTypeTestsModule::allocateByteArrays() {
std::stable_sort(ByteArrayInfos.begin(), ByteArrayInfos.end(),
[](const ByteArrayInfo &BAI1, const ByteArrayInfo &BAI2) {
return BAI1.BitSize > BAI2.BitSize;
@ -354,9 +365,9 @@ void LowerTypeTests::allocateByteArrays() {
cast<GlobalVariable>(BAI->Mask->getOperand(0))->eraseFromParent();
}
Constant *ByteArrayConst = ConstantDataArray::get(M->getContext(), BAB.Bytes);
Constant *ByteArrayConst = ConstantDataArray::get(M.getContext(), BAB.Bytes);
auto ByteArray =
new GlobalVariable(*M, ByteArrayConst->getType(), /*isConstant=*/true,
new GlobalVariable(M, ByteArrayConst->getType(), /*isConstant=*/true,
GlobalValue::PrivateLinkage, ByteArrayConst);
for (unsigned I = 0; I != ByteArrayInfos.size(); ++I) {
@ -374,7 +385,7 @@ void LowerTypeTests::allocateByteArrays() {
BAI->ByteArray->replaceAllUsesWith(GEP);
} else {
GlobalAlias *Alias = GlobalAlias::create(
Int8Ty, 0, GlobalValue::PrivateLinkage, "bits", GEP, M);
Int8Ty, 0, GlobalValue::PrivateLinkage, "bits", GEP, &M);
BAI->ByteArray->replaceAllUsesWith(Alias);
}
BAI->ByteArray->eraseFromParent();
@ -388,8 +399,9 @@ void LowerTypeTests::allocateByteArrays() {
/// Build a test that bit BitOffset is set in BSI, where
/// BitSetGlobal is a global containing the bits in BSI.
Value *LowerTypeTests::createBitSetTest(IRBuilder<> &B, BitSetInfo &BSI,
ByteArrayInfo *&BAI, Value *BitOffset) {
Value *LowerTypeTestsModule::createBitSetTest(IRBuilder<> &B, BitSetInfo &BSI,
ByteArrayInfo *&BAI,
Value *BitOffset) {
if (BSI.BitSize <= 64) {
// If the bit set is sufficiently small, we can avoid a load by bit testing
// a constant.
@ -418,7 +430,7 @@ Value *LowerTypeTests::createBitSetTest(IRBuilder<> &B, BitSetInfo &BSI,
// improving the security of the CFI mechanism based on this pass.
ByteArray = GlobalAlias::create(BAI->ByteArray->getValueType(), 0,
GlobalValue::PrivateLinkage, "bits_use",
ByteArray, M);
ByteArray, &M);
}
Value *ByteAddr = B.CreateGEP(Ty, ByteArray, BitOffset);
@ -431,15 +443,15 @@ Value *LowerTypeTests::createBitSetTest(IRBuilder<> &B, BitSetInfo &BSI,
/// Lower a llvm.type.test call to its implementation. Returns the value to
/// replace the call with.
Value *LowerTypeTests::lowerBitSetCall(
Value *LowerTypeTestsModule::lowerBitSetCall(
CallInst *CI, BitSetInfo &BSI, ByteArrayInfo *&BAI,
Constant *CombinedGlobalIntAddr,
const DenseMap<GlobalObject *, uint64_t> &GlobalLayout) {
Value *Ptr = CI->getArgOperand(0);
const DataLayout &DL = M->getDataLayout();
const DataLayout &DL = M.getDataLayout();
if (BSI.containsValue(DL, GlobalLayout, Ptr))
return ConstantInt::getTrue(M->getContext());
return ConstantInt::getTrue(M.getContext());
Constant *OffsetedGlobalAsInt = ConstantExpr::getAdd(
CombinedGlobalIntAddr, ConstantInt::get(IntPtrTy, BSI.ByteOffset));
@ -503,14 +515,14 @@ Value *LowerTypeTests::lowerBitSetCall(
/// Given a disjoint set of type identifiers and globals, lay out the globals,
/// build the bit sets and lower the llvm.type.test calls.
void LowerTypeTests::buildBitSetsFromGlobalVariables(
void LowerTypeTestsModule::buildBitSetsFromGlobalVariables(
ArrayRef<Metadata *> TypeIds, ArrayRef<GlobalVariable *> Globals) {
// Build a new global with the combined contents of the referenced globals.
// This global is a struct whose even-indexed elements contain the original
// contents of the referenced globals and whose odd-indexed elements contain
// any padding required to align the next element to the next power of 2.
std::vector<Constant *> GlobalInits;
const DataLayout &DL = M->getDataLayout();
const DataLayout &DL = M.getDataLayout();
for (GlobalVariable *G : Globals) {
GlobalInits.push_back(G->getInitializer());
uint64_t InitSize = DL.getTypeAllocSize(G->getValueType());
@ -528,9 +540,9 @@ void LowerTypeTests::buildBitSetsFromGlobalVariables(
}
if (!GlobalInits.empty())
GlobalInits.pop_back();
Constant *NewInit = ConstantStruct::getAnon(M->getContext(), GlobalInits);
Constant *NewInit = ConstantStruct::getAnon(M.getContext(), GlobalInits);
auto *CombinedGlobal =
new GlobalVariable(*M, NewInit->getType(), /*isConstant=*/true,
new GlobalVariable(M, NewInit->getType(), /*isConstant=*/true,
GlobalValue::PrivateLinkage, NewInit);
StructType *NewTy = cast<StructType>(NewInit->getType());
@ -559,7 +571,7 @@ void LowerTypeTests::buildBitSetsFromGlobalVariables(
assert(Globals[I]->getType()->getAddressSpace() == 0);
GlobalAlias *GAlias = GlobalAlias::create(NewTy->getElementType(I * 2), 0,
Globals[I]->getLinkage(), "",
CombinedGlobalElemPtr, M);
CombinedGlobalElemPtr, &M);
GAlias->setVisibility(Globals[I]->getVisibility());
GAlias->takeName(Globals[I]);
Globals[I]->replaceAllUsesWith(GAlias);
@ -568,7 +580,7 @@ void LowerTypeTests::buildBitSetsFromGlobalVariables(
}
}
void LowerTypeTests::lowerTypeTestCalls(
void LowerTypeTestsModule::lowerTypeTestCalls(
ArrayRef<Metadata *> TypeIds, Constant *CombinedGlobalAddr,
const DenseMap<GlobalObject *, uint64_t> &GlobalLayout) {
Constant *CombinedGlobalIntAddr =
@ -599,7 +611,7 @@ void LowerTypeTests::lowerTypeTestCalls(
}
}
void LowerTypeTests::verifyTypeMDNode(GlobalObject *GO, MDNode *Type) {
void LowerTypeTestsModule::verifyTypeMDNode(GlobalObject *GO, MDNode *Type) {
if (Type->getNumOperands() != 2)
report_fatal_error("All operands of type metadata must have 2 elements");
@ -623,7 +635,7 @@ void LowerTypeTests::verifyTypeMDNode(GlobalObject *GO, MDNode *Type) {
static const unsigned kX86JumpTableEntrySize = 8;
unsigned LowerTypeTests::getJumpTableEntrySize() {
unsigned LowerTypeTestsModule::getJumpTableEntrySize() {
return kX86JumpTableEntrySize;
}
@ -631,9 +643,9 @@ unsigned LowerTypeTests::getJumpTableEntrySize() {
// consists of an instruction sequence containing a relative branch to Dest. The
// constant will be laid out at address Src+(Len*Distance) where Len is the
// target-specific jump table entry size.
Constant *LowerTypeTests::createJumpTableEntry(GlobalObject *Src,
Function *Dest,
unsigned Distance) {
Constant *LowerTypeTestsModule::createJumpTableEntry(GlobalObject *Src,
Function *Dest,
unsigned Distance) {
const unsigned kJmpPCRel32Code = 0xe9;
const unsigned kInt3Code = 0xcc;
@ -657,16 +669,16 @@ Constant *LowerTypeTests::createJumpTableEntry(GlobalObject *Src,
return ConstantStruct::getAnon(Fields, /*Packed=*/true);
}
Type *LowerTypeTests::getJumpTableEntryType() {
return StructType::get(M->getContext(),
Type *LowerTypeTestsModule::getJumpTableEntryType() {
return StructType::get(M.getContext(),
{Int8Ty, Int32Ty, Int8Ty, Int8Ty, Int8Ty},
/*Packed=*/true);
}
/// Given a disjoint set of type identifiers and functions, build the bit sets
/// and lower the llvm.type.test calls, architecture dependently.
void LowerTypeTests::buildBitSetsFromFunctions(ArrayRef<Metadata *> TypeIds,
ArrayRef<Function *> Functions) {
void LowerTypeTestsModule::buildBitSetsFromFunctions(
ArrayRef<Metadata *> TypeIds, ArrayRef<Function *> Functions) {
if (Arch == Triple::x86 || Arch == Triple::x86_64)
buildBitSetsFromFunctionsX86(TypeIds, Functions);
else if (Arch == Triple::wasm32 || Arch == Triple::wasm64)
@ -677,7 +689,7 @@ void LowerTypeTests::buildBitSetsFromFunctions(ArrayRef<Metadata *> TypeIds,
/// Given a disjoint set of type identifiers and functions, build a jump table
/// for the functions, build the bit sets and lower the llvm.type.test calls.
void LowerTypeTests::buildBitSetsFromFunctionsX86(
void LowerTypeTestsModule::buildBitSetsFromFunctionsX86(
ArrayRef<Metadata *> TypeIds, ArrayRef<Function *> Functions) {
// Unlike the global bitset builder, the function bitset builder cannot
// re-arrange functions in a particular order and base its calculations on the
@ -769,7 +781,7 @@ void LowerTypeTests::buildBitSetsFromFunctionsX86(
// Create a constant to hold the jump table.
ArrayType *JumpTableType =
ArrayType::get(getJumpTableEntryType(), Functions.size());
auto JumpTable = new GlobalVariable(*M, JumpTableType,
auto JumpTable = new GlobalVariable(M, JumpTableType,
/*isConstant=*/true,
GlobalValue::PrivateLinkage, nullptr);
JumpTable->setSection(ObjectFormat == Triple::MachO
@ -792,7 +804,7 @@ void LowerTypeTests::buildBitSetsFromFunctionsX86(
assert(Functions[I]->getType()->getAddressSpace() == 0);
GlobalAlias *GAlias = GlobalAlias::create(Functions[I]->getValueType(), 0,
Functions[I]->getLinkage(), "",
CombinedGlobalElemPtr, M);
CombinedGlobalElemPtr, &M);
GAlias->setVisibility(Functions[I]->getVisibility());
GAlias->takeName(Functions[I]);
Functions[I]->replaceAllUsesWith(GAlias);
@ -816,7 +828,7 @@ void LowerTypeTests::buildBitSetsFromFunctionsX86(
/// table in the backend, it will assign the given indexes.
/// Note: Dynamic linking is not supported, as the WebAssembly ABI has not yet
/// been finalized.
void LowerTypeTests::buildBitSetsFromFunctionsWASM(
void LowerTypeTestsModule::buildBitSetsFromFunctionsWASM(
ArrayRef<Metadata *> TypeIds, ArrayRef<Function *> Functions) {
assert(!Functions.empty());
@ -840,12 +852,11 @@ void LowerTypeTests::buildBitSetsFromFunctionsWASM(
// The indirect function table index space starts at zero, so pass a NULL
// pointer as the subtracted "jump table" offset.
lowerTypeTestCalls(TypeIds,
ConstantPointerNull::get(cast<PointerType>(Int32PtrTy)),
lowerTypeTestCalls(TypeIds, ConstantPointerNull::get(Int32PtrTy),
GlobalLayout);
}
void LowerTypeTests::buildBitSetsFromDisjointSet(
void LowerTypeTestsModule::buildBitSetsFromDisjointSet(
ArrayRef<Metadata *> TypeIds, ArrayRef<GlobalObject *> Globals) {
llvm::DenseMap<Metadata *, uint64_t> TypeIdIndices;
for (unsigned I = 0; I != TypeIds.size(); ++I)
@ -917,9 +928,16 @@ void LowerTypeTests::buildBitSetsFromDisjointSet(
}
/// Lower all type tests in this module.
bool LowerTypeTests::lower() {
LowerTypeTestsModule::LowerTypeTestsModule(Module &M) : M(M) {
Triple TargetTriple(M.getTargetTriple());
LinkerSubsectionsViaSymbols = TargetTriple.isMacOSX();
Arch = TargetTriple.getArch();
ObjectFormat = TargetTriple.getObjectFormat();
}
bool LowerTypeTestsModule::lower() {
Function *TypeTestFunc =
M->getFunction(Intrinsic::getName(Intrinsic::type_test));
M.getFunction(Intrinsic::getName(Intrinsic::type_test));
if (!TypeTestFunc || TypeTestFunc->use_empty())
return false;
@ -936,7 +954,7 @@ bool LowerTypeTests::lower() {
llvm::DenseMap<Metadata *, unsigned> TypeIdIndices;
unsigned I = 0;
SmallVector<MDNode *, 2> Types;
for (GlobalObject &GO : M->global_objects()) {
for (GlobalObject &GO : M.global_objects()) {
Types.clear();
GO.getMetadata(LLVMContext::MD_type, Types);
for (MDNode *Type : Types) {
@ -969,7 +987,7 @@ bool LowerTypeTests::lower() {
GlobalClassesTy::member_iterator CurSet = GlobalClasses.findLeader(GCI);
// Add the referenced globals to the type identifier's equivalence class.
for (GlobalObject &GO : M->global_objects()) {
for (GlobalObject &GO : M.global_objects()) {
Types.clear();
GO.getMetadata(LLVMContext::MD_type, Types);
for (MDNode *Type : Types)
@ -1035,36 +1053,10 @@ bool LowerTypeTests::lower() {
return true;
}
// Initialization helper shared by the old and the new PM.
static void init(LowerTypeTests *LTT, Module &M) {
LTT->M = &M;
const DataLayout &DL = M.getDataLayout();
Triple TargetTriple(M.getTargetTriple());
LTT->LinkerSubsectionsViaSymbols = TargetTriple.isMacOSX();
LTT->Arch = TargetTriple.getArch();
LTT->ObjectFormat = TargetTriple.getObjectFormat();
LTT->Int1Ty = Type::getInt1Ty(M.getContext());
LTT->Int8Ty = Type::getInt8Ty(M.getContext());
LTT->Int32Ty = Type::getInt32Ty(M.getContext());
LTT->Int32PtrTy = PointerType::getUnqual(LTT->Int32Ty);
LTT->Int64Ty = Type::getInt64Ty(M.getContext());
LTT->IntPtrTy = DL.getIntPtrType(M.getContext(), 0);
LTT->TypeTestCallSites.clear();
LTT->IndirectIndex = 1;
}
bool LowerTypeTests::runOnModule(Module &M) {
if (skipModule(M))
return false;
init(this, M);
return lower();
}
PreservedAnalyses LowerTypeTestsPass::run(Module &M,
ModuleAnalysisManager &AM) {
LowerTypeTests Impl;
init(&Impl, M);
bool Changed = Impl.lower();
bool Changed = LowerTypeTestsModule(M).lower();
if (!Changed)
return PreservedAnalyses::all();
return PreservedAnalyses::none();