#include "llvm/Transforms/IPO/LowerTypeTests.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/EquivalenceClasses.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/Analysis/TypeMetadataUtils.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalAlias.h"
#include "llvm/IR/GlobalObject.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/ModuleSummaryIndex.h"
#include "llvm/IR/ModuleSummaryIndexYAML.h"
#include "llvm/IR/Operator.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/ReplaceConstant.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Use.h"
#include "llvm/IR/User.h"
#include "llvm/IR/Value.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/TrailingObjects.h"
#include "llvm/Support/YAMLTraits.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TargetParser/Triple.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/ModuleUtils.h"
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <memory>
#include <set>
#include <string>
#include <system_error>
#include <utility>
#include <vector>
usingnamespacellvm;
usingnamespacelowertypetests;
#define DEBUG_TYPE …
STATISTIC(ByteArraySizeBits, "Byte array size in bits");
STATISTIC(ByteArraySizeBytes, "Byte array size in bytes");
STATISTIC(NumByteArraysCreated, "Number of byte arrays created");
STATISTIC(NumTypeTestCallsLowered, "Number of type test calls lowered");
STATISTIC(NumTypeIdDisjointSets, "Number of disjoint sets of type identifiers");
static cl::opt<bool> AvoidReuse(
"lowertypetests-avoid-reuse",
cl::desc("Try to avoid reuse of byte array addresses using aliases"),
cl::Hidden, cl::init(true));
static cl::opt<PassSummaryAction> ClSummaryAction(
"lowertypetests-summary-action",
cl::desc("What to do with the summary when running this pass"),
cl::values(clEnumValN(PassSummaryAction::None, "none", "Do nothing"),
clEnumValN(PassSummaryAction::Import, "import",
"Import typeid resolutions from summary and globals"),
clEnumValN(PassSummaryAction::Export, "export",
"Export typeid resolutions to summary and globals")),
cl::Hidden);
static cl::opt<std::string> ClReadSummary(
"lowertypetests-read-summary",
cl::desc("Read summary from given YAML file before running pass"),
cl::Hidden);
static cl::opt<std::string> ClWriteSummary(
"lowertypetests-write-summary",
cl::desc("Write summary to given YAML file after running pass"),
cl::Hidden);
static cl::opt<bool>
ClDropTypeTests("lowertypetests-drop-type-tests",
cl::desc("Simply drop type test assume sequences"),
cl::Hidden, cl::init(false));
bool BitSetInfo::containsGlobalOffset(uint64_t Offset) const { … }
void BitSetInfo::print(raw_ostream &OS) const { … }
BitSetInfo BitSetBuilder::build() { … }
void GlobalLayoutBuilder::addFragment(const std::set<uint64_t> &F) { … }
void ByteArrayBuilder::allocate(const std::set<uint64_t> &Bits,
uint64_t BitSize, uint64_t &AllocByteOffset,
uint8_t &AllocMask) { … }
bool lowertypetests::isJumpTableCanonical(Function *F) { … }
namespace {
struct ByteArrayInfo { … };
class GlobalTypeMember final : TrailingObjects<GlobalTypeMember, MDNode *> { … };
struct ICallBranchFunnel final
: TrailingObjects<ICallBranchFunnel, GlobalTypeMember *> { … };
struct ScopedSaveAliaseesAndUsed { … };
class LowerTypeTestsModule { … };
}
BitSetInfo LowerTypeTestsModule::buildBitSet(
Metadata *TypeId,
const DenseMap<GlobalTypeMember *, uint64_t> &GlobalLayout) { … }
static Value *createMaskedBitTest(IRBuilder<> &B, Value *Bits,
Value *BitOffset) { … }
ByteArrayInfo *LowerTypeTestsModule::createByteArray(BitSetInfo &BSI) { … }
void LowerTypeTestsModule::allocateByteArrays() { … }
Value *LowerTypeTestsModule::createBitSetTest(IRBuilder<> &B,
const TypeIdLowering &TIL,
Value *BitOffset) { … }
static bool isKnownTypeIdMember(Metadata *TypeId, const DataLayout &DL,
Value *V, uint64_t COffset) { … }
Value *LowerTypeTestsModule::lowerTypeTestCall(Metadata *TypeId, CallInst *CI,
const TypeIdLowering &TIL) { … }
void LowerTypeTestsModule::buildBitSetsFromGlobalVariables(
ArrayRef<Metadata *> TypeIds, ArrayRef<GlobalTypeMember *> Globals) { … }
bool LowerTypeTestsModule::shouldExportConstantsAsAbsoluteSymbols() { … }
uint8_t *LowerTypeTestsModule::exportTypeId(StringRef TypeId,
const TypeIdLowering &TIL) { … }
LowerTypeTestsModule::TypeIdLowering
LowerTypeTestsModule::importTypeId(StringRef TypeId) { … }
void LowerTypeTestsModule::importTypeTest(CallInst *CI) { … }
void LowerTypeTestsModule::importFunction(
Function *F, bool isJumpTableCanonical,
std::vector<GlobalAlias *> &AliasesToErase) { … }
void LowerTypeTestsModule::lowerTypeTestCalls(
ArrayRef<Metadata *> TypeIds, Constant *CombinedGlobalAddr,
const DenseMap<GlobalTypeMember *, uint64_t> &GlobalLayout) { … }
void LowerTypeTestsModule::verifyTypeMDNode(GlobalObject *GO, MDNode *Type) { … }
static const unsigned kX86JumpTableEntrySize = …;
static const unsigned kX86IBTJumpTableEntrySize = …;
static const unsigned kARMJumpTableEntrySize = …;
static const unsigned kARMBTIJumpTableEntrySize = …;
static const unsigned kARMv6MJumpTableEntrySize = …;
static const unsigned kRISCVJumpTableEntrySize = …;
static const unsigned kLOONGARCH64JumpTableEntrySize = …;
bool LowerTypeTestsModule::hasBranchTargetEnforcement() { … }
unsigned LowerTypeTestsModule::getJumpTableEntrySize() { … }
void LowerTypeTestsModule::createJumpTableEntry(
raw_ostream &AsmOS, raw_ostream &ConstraintOS,
Triple::ArchType JumpTableArch, SmallVectorImpl<Value *> &AsmArgs,
Function *Dest) { … }
Type *LowerTypeTestsModule::getJumpTableEntryType() { … }
void LowerTypeTestsModule::buildBitSetsFromFunctions(
ArrayRef<Metadata *> TypeIds, ArrayRef<GlobalTypeMember *> Functions) { … }
void LowerTypeTestsModule::moveInitializerToModuleConstructor(
GlobalVariable *GV) { … }
void LowerTypeTestsModule::findGlobalVariableUsersOf(
Constant *C, SmallSetVector<GlobalVariable *, 8> &Out) { … }
void LowerTypeTestsModule::replaceWeakDeclarationWithJumpTablePtr(
Function *F, Constant *JT, bool IsJumpTableCanonical) { … }
static bool isThumbFunction(Function *F, Triple::ArchType ModuleArch) { … }
Triple::ArchType LowerTypeTestsModule::selectJumpTableArmEncoding(
ArrayRef<GlobalTypeMember *> Functions) { … }
void LowerTypeTestsModule::createJumpTable(
Function *F, ArrayRef<GlobalTypeMember *> Functions) { … }
void LowerTypeTestsModule::buildBitSetsFromFunctionsNative(
ArrayRef<Metadata *> TypeIds, ArrayRef<GlobalTypeMember *> Functions) { … }
void LowerTypeTestsModule::buildBitSetsFromFunctionsWASM(
ArrayRef<Metadata *> TypeIds, ArrayRef<GlobalTypeMember *> Functions) { … }
void LowerTypeTestsModule::buildBitSetsFromDisjointSet(
ArrayRef<Metadata *> TypeIds, ArrayRef<GlobalTypeMember *> Globals,
ArrayRef<ICallBranchFunnel *> ICallBranchFunnels) { … }
LowerTypeTestsModule::LowerTypeTestsModule(
Module &M, ModuleAnalysisManager &AM, ModuleSummaryIndex *ExportSummary,
const ModuleSummaryIndex *ImportSummary, bool DropTypeTests)
: … { … }
bool LowerTypeTestsModule::runForTesting(Module &M, ModuleAnalysisManager &AM) { … }
static bool isDirectCall(Use& U) { … }
void LowerTypeTestsModule::replaceCfiUses(Function *Old, Value *New,
bool IsJumpTableCanonical) { … }
void LowerTypeTestsModule::replaceDirectCalls(Value *Old, Value *New) { … }
static void dropTypeTests(Module &M, Function &TypeTestFunc) { … }
bool LowerTypeTestsModule::lower() { … }
PreservedAnalyses LowerTypeTestsPass::run(Module &M,
ModuleAnalysisManager &AM) { … }