Index: include/llvm/IR/SlotTracker.h =================================================================== --- /dev/null +++ include/llvm/IR/SlotTracker.h @@ -0,0 +1,150 @@ +//===-- llvm/IR/SlotTracker.h - Slot numbers for unnamed values -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the SlotTracker class. This class +// enumerates slot numbers for unnamed values, metadata nodes, and attribute +// sets. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_SLOTTRACKER_H +#define LLVM_IR_SLOTTRACKER_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/IR/Attributes.h" + +namespace llvm { + +class Function; +class GlobalValue; +class Instruction; +class MDNode; +class Module; +class Value; + +/// This class provides computation of slot numbers for LLVM Assembly writing. +/// +class SlotTracker { +public: + /// ValueMap - A mapping of Values to slot numbers. + typedef DenseMap ValueMap; + +private: + /// TheModule - The module for which we are holding slot numbers. + const Module *TheModule; + + /// TheFunction - The function for which we are holding slot numbers. + const Function *TheFunction; + bool FunctionProcessed; + bool ShouldInitializeAllMetadata; + + /// mMap - The slot map for the module level data. + ValueMap mMap; + unsigned mNext; + + /// fMap - The slot map for the function level data. + ValueMap fMap; + unsigned fNext; + + /// mdnMap - Map for MDNodes. + DenseMap mdnMap; + unsigned mdnNext; + + /// asMap - The slot map for attribute sets. + DenseMap asMap; + unsigned asNext; + +public: + /// Construct from a module. + /// + /// If \c ShouldInitializeAllMetadata, initializes all metadata in all + /// functions, giving correct numbering for metadata referenced only from + /// within a function (even if no functions have been initialized). + explicit SlotTracker(const Module *M, + bool ShouldInitializeAllMetadata = false); + /// Construct from a function, starting out in incorp state. + /// + /// If \c ShouldInitializeAllMetadata, initializes all metadata in all + /// functions, giving correct numbering for metadata referenced only from + /// within a function (even if no functions have been initialized). + explicit SlotTracker(const Function *F, + bool ShouldInitializeAllMetadata = false); + + /// Return the slot number of the specified value in it's type + /// plane. If something is not in the SlotTracker, return -1. + int getLocalSlot(const Value *V); + int getGlobalSlot(const GlobalValue *V); + int getMetadataSlot(const MDNode *N); + int getAttributeGroupSlot(AttributeSet AS); + + /// If you'd like to deal with a function instead of just a module, use + /// this method to get its data into the SlotTracker. + void incorporateFunction(const Function *F) { + TheFunction = F; + FunctionProcessed = false; + } + + const Function *getFunction() const { return TheFunction; } + + /// After calling incorporateFunction, use this method to remove the + /// most recently incorporated function from the SlotTracker. This + /// will reset the state of the machine back to just the module contents. + void purgeFunction(); + + /// MDNode map iterators. + typedef DenseMap::iterator mdn_iterator; + mdn_iterator mdn_begin() { return mdnMap.begin(); } + mdn_iterator mdn_end() { return mdnMap.end(); } + unsigned mdn_size() const { return mdnMap.size(); } + bool mdn_empty() const { return mdnMap.empty(); } + + /// AttributeSet map iterators. + typedef DenseMap::iterator as_iterator; + as_iterator as_begin() { return asMap.begin(); } + as_iterator as_end() { return asMap.end(); } + unsigned as_size() const { return asMap.size(); } + bool as_empty() const { return asMap.empty(); } + + /// This function does the actual initialization. + void initialize(); + + // Implementation Details +private: + /// CreateModuleSlot - Insert the specified GlobalValue* into the slot table. + void CreateModuleSlot(const GlobalValue *V); + + /// CreateMetadataSlot - Insert the specified MDNode* into the slot table. + void CreateMetadataSlot(const MDNode *N); + + /// CreateFunctionSlot - Insert the specified Value* into the slot table. + void CreateFunctionSlot(const Value *V); + + /// \brief Insert the specified AttributeSet into the slot table. + void CreateAttributeSetSlot(AttributeSet AS); + + /// Add all of the module level global variables (and their initializers) + /// and function declarations, but not the contents of those functions. + void processModule(); + + /// Add all of the functions arguments, basic blocks, and instructions. + void processFunction(); + + /// Add all of the metadata from a function. + void processFunctionMetadata(const Function &F); + + /// Add all of the metadata from an instruction. + void processInstructionMetadata(const Instruction &I); + + SlotTracker(const SlotTracker &) = delete; + void operator=(const SlotTracker &) = delete; +}; + +} // end namespace llvm + +#endif Index: lib/IR/AsmWriter.cpp =================================================================== --- lib/IR/AsmWriter.cpp +++ lib/IR/AsmWriter.cpp @@ -31,6 +31,7 @@ #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/IR/Operator.h" +#include "llvm/IR/SlotTracker.h" #include "llvm/IR/Statepoint.h" #include "llvm/IR/TypeFinder.h" #include "llvm/IR/UseListOrder.h" @@ -540,127 +541,6 @@ OS << '>'; } -namespace { -//===----------------------------------------------------------------------===// -// SlotTracker Class: Enumerate slot numbers for unnamed values -//===----------------------------------------------------------------------===// -/// This class provides computation of slot numbers for LLVM Assembly writing. -/// -class SlotTracker { -public: - /// ValueMap - A mapping of Values to slot numbers. - typedef DenseMap ValueMap; - -private: - /// TheModule - The module for which we are holding slot numbers. - const Module* TheModule; - - /// TheFunction - The function for which we are holding slot numbers. - const Function* TheFunction; - bool FunctionProcessed; - bool ShouldInitializeAllMetadata; - - /// mMap - The slot map for the module level data. - ValueMap mMap; - unsigned mNext; - - /// fMap - The slot map for the function level data. - ValueMap fMap; - unsigned fNext; - - /// mdnMap - Map for MDNodes. - DenseMap mdnMap; - unsigned mdnNext; - - /// asMap - The slot map for attribute sets. - DenseMap asMap; - unsigned asNext; -public: - /// Construct from a module. - /// - /// If \c ShouldInitializeAllMetadata, initializes all metadata in all - /// functions, giving correct numbering for metadata referenced only from - /// within a function (even if no functions have been initialized). - explicit SlotTracker(const Module *M, - bool ShouldInitializeAllMetadata = false); - /// Construct from a function, starting out in incorp state. - /// - /// If \c ShouldInitializeAllMetadata, initializes all metadata in all - /// functions, giving correct numbering for metadata referenced only from - /// within a function (even if no functions have been initialized). - explicit SlotTracker(const Function *F, - bool ShouldInitializeAllMetadata = false); - - /// Return the slot number of the specified value in it's type - /// plane. If something is not in the SlotTracker, return -1. - int getLocalSlot(const Value *V); - int getGlobalSlot(const GlobalValue *V); - int getMetadataSlot(const MDNode *N); - int getAttributeGroupSlot(AttributeSet AS); - - /// If you'd like to deal with a function instead of just a module, use - /// this method to get its data into the SlotTracker. - void incorporateFunction(const Function *F) { - TheFunction = F; - FunctionProcessed = false; - } - - const Function *getFunction() const { return TheFunction; } - - /// After calling incorporateFunction, use this method to remove the - /// most recently incorporated function from the SlotTracker. This - /// will reset the state of the machine back to just the module contents. - void purgeFunction(); - - /// MDNode map iterators. - typedef DenseMap::iterator mdn_iterator; - mdn_iterator mdn_begin() { return mdnMap.begin(); } - mdn_iterator mdn_end() { return mdnMap.end(); } - unsigned mdn_size() const { return mdnMap.size(); } - bool mdn_empty() const { return mdnMap.empty(); } - - /// AttributeSet map iterators. - typedef DenseMap::iterator as_iterator; - as_iterator as_begin() { return asMap.begin(); } - as_iterator as_end() { return asMap.end(); } - unsigned as_size() const { return asMap.size(); } - bool as_empty() const { return asMap.empty(); } - - /// This function does the actual initialization. - inline void initialize(); - - // Implementation Details -private: - /// CreateModuleSlot - Insert the specified GlobalValue* into the slot table. - void CreateModuleSlot(const GlobalValue *V); - - /// CreateMetadataSlot - Insert the specified MDNode* into the slot table. - void CreateMetadataSlot(const MDNode *N); - - /// CreateFunctionSlot - Insert the specified Value* into the slot table. - void CreateFunctionSlot(const Value *V); - - /// \brief Insert the specified AttributeSet into the slot table. - void CreateAttributeSetSlot(AttributeSet AS); - - /// Add all of the module level global variables (and their initializers) - /// and function declarations, but not the contents of those functions. - void processModule(); - - /// Add all of the functions arguments, basic blocks, and instructions. - void processFunction(); - - /// Add all of the metadata from a function. - void processFunctionMetadata(const Function &F); - - /// Add all of the metadata from an instruction. - void processInstructionMetadata(const Instruction &I); - - SlotTracker(const SlotTracker &) = delete; - void operator=(const SlotTracker &) = delete; -}; -} // namespace - static SlotTracker *createSlotTracker(const Module *M) { return new SlotTracker(M); } @@ -688,259 +568,6 @@ return nullptr; } -#if 0 -#define ST_DEBUG(X) dbgs() << X -#else -#define ST_DEBUG(X) -#endif - -// Module level constructor. Causes the contents of the Module (sans functions) -// to be added to the slot table. -SlotTracker::SlotTracker(const Module *M, bool ShouldInitializeAllMetadata) - : TheModule(M), TheFunction(nullptr), FunctionProcessed(false), - ShouldInitializeAllMetadata(ShouldInitializeAllMetadata), mNext(0), - fNext(0), mdnNext(0), asNext(0) {} - -// Function level constructor. Causes the contents of the Module and the one -// function provided to be added to the slot table. -SlotTracker::SlotTracker(const Function *F, bool ShouldInitializeAllMetadata) - : TheModule(F ? F->getParent() : nullptr), TheFunction(F), - FunctionProcessed(false), - ShouldInitializeAllMetadata(ShouldInitializeAllMetadata), mNext(0), - fNext(0), mdnNext(0), asNext(0) {} - -inline void SlotTracker::initialize() { - if (TheModule) { - processModule(); - TheModule = nullptr; ///< Prevent re-processing next time we're called. - } - - if (TheFunction && !FunctionProcessed) - processFunction(); -} - -// Iterate through all the global variables, functions, and global -// variable initializers and create slots for them. -void SlotTracker::processModule() { - ST_DEBUG("begin processModule!\n"); - - // Add all of the unnamed global variables to the value table. - for (Module::const_global_iterator I = TheModule->global_begin(), - E = TheModule->global_end(); I != E; ++I) { - if (!I->hasName()) - CreateModuleSlot(I); - } - - // Add metadata used by named metadata. - for (Module::const_named_metadata_iterator - I = TheModule->named_metadata_begin(), - E = TheModule->named_metadata_end(); I != E; ++I) { - const NamedMDNode *NMD = I; - for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) - CreateMetadataSlot(NMD->getOperand(i)); - } - - for (Module::const_iterator I = TheModule->begin(), E = TheModule->end(); - I != E; ++I) { - if (!I->hasName()) - // Add all the unnamed functions to the table. - CreateModuleSlot(I); - - if (ShouldInitializeAllMetadata) - processFunctionMetadata(*I); - - // Add all the function attributes to the table. - // FIXME: Add attributes of other objects? - AttributeSet FnAttrs = I->getAttributes().getFnAttributes(); - if (FnAttrs.hasAttributes(AttributeSet::FunctionIndex)) - CreateAttributeSetSlot(FnAttrs); - } - - ST_DEBUG("end processModule!\n"); -} - -// Process the arguments, basic blocks, and instructions of a function. -void SlotTracker::processFunction() { - ST_DEBUG("begin processFunction!\n"); - fNext = 0; - - // Add all the function arguments with no names. - for(Function::const_arg_iterator AI = TheFunction->arg_begin(), - AE = TheFunction->arg_end(); AI != AE; ++AI) - if (!AI->hasName()) - CreateFunctionSlot(AI); - - ST_DEBUG("Inserting Instructions:\n"); - - // Add all of the basic blocks and instructions with no names. - for (auto &BB : *TheFunction) { - if (!BB.hasName()) - CreateFunctionSlot(&BB); - - processFunctionMetadata(*TheFunction); - - for (auto &I : BB) { - if (!I.getType()->isVoidTy() && !I.hasName()) - CreateFunctionSlot(&I); - - // We allow direct calls to any llvm.foo function here, because the - // target may not be linked into the optimizer. - if (const CallInst *CI = dyn_cast(&I)) { - // Add all the call attributes to the table. - AttributeSet Attrs = CI->getAttributes().getFnAttributes(); - if (Attrs.hasAttributes(AttributeSet::FunctionIndex)) - CreateAttributeSetSlot(Attrs); - } else if (const InvokeInst *II = dyn_cast(&I)) { - // Add all the call attributes to the table. - AttributeSet Attrs = II->getAttributes().getFnAttributes(); - if (Attrs.hasAttributes(AttributeSet::FunctionIndex)) - CreateAttributeSetSlot(Attrs); - } - } - } - - FunctionProcessed = true; - - ST_DEBUG("end processFunction!\n"); -} - -void SlotTracker::processFunctionMetadata(const Function &F) { - SmallVector, 4> MDs; - for (auto &BB : F) { - F.getAllMetadata(MDs); - for (auto &MD : MDs) - CreateMetadataSlot(MD.second); - - for (auto &I : BB) - processInstructionMetadata(I); - } -} - -void SlotTracker::processInstructionMetadata(const Instruction &I) { - // Process metadata used directly by intrinsics. - if (const CallInst *CI = dyn_cast(&I)) - if (Function *F = CI->getCalledFunction()) - if (F->isIntrinsic()) - for (auto &Op : I.operands()) - if (auto *V = dyn_cast_or_null(Op)) - if (MDNode *N = dyn_cast(V->getMetadata())) - CreateMetadataSlot(N); - - // Process metadata attached to this instruction. - SmallVector, 4> MDs; - I.getAllMetadata(MDs); - for (auto &MD : MDs) - CreateMetadataSlot(MD.second); -} - -/// Clean up after incorporating a function. This is the only way to get out of -/// the function incorporation state that affects get*Slot/Create*Slot. Function -/// incorporation state is indicated by TheFunction != 0. -void SlotTracker::purgeFunction() { - ST_DEBUG("begin purgeFunction!\n"); - fMap.clear(); // Simply discard the function level map - TheFunction = nullptr; - FunctionProcessed = false; - ST_DEBUG("end purgeFunction!\n"); -} - -/// getGlobalSlot - Get the slot number of a global value. -int SlotTracker::getGlobalSlot(const GlobalValue *V) { - // Check for uninitialized state and do lazy initialization. - initialize(); - - // Find the value in the module map - ValueMap::iterator MI = mMap.find(V); - return MI == mMap.end() ? -1 : (int)MI->second; -} - -/// getMetadataSlot - Get the slot number of a MDNode. -int SlotTracker::getMetadataSlot(const MDNode *N) { - // Check for uninitialized state and do lazy initialization. - initialize(); - - // Find the MDNode in the module map - mdn_iterator MI = mdnMap.find(N); - return MI == mdnMap.end() ? -1 : (int)MI->second; -} - - -/// getLocalSlot - Get the slot number for a value that is local to a function. -int SlotTracker::getLocalSlot(const Value *V) { - assert(!isa(V) && "Can't get a constant or global slot with this!"); - - // Check for uninitialized state and do lazy initialization. - initialize(); - - ValueMap::iterator FI = fMap.find(V); - return FI == fMap.end() ? -1 : (int)FI->second; -} - -int SlotTracker::getAttributeGroupSlot(AttributeSet AS) { - // Check for uninitialized state and do lazy initialization. - initialize(); - - // Find the AttributeSet in the module map. - as_iterator AI = asMap.find(AS); - return AI == asMap.end() ? -1 : (int)AI->second; -} - -/// CreateModuleSlot - Insert the specified GlobalValue* into the slot table. -void SlotTracker::CreateModuleSlot(const GlobalValue *V) { - assert(V && "Can't insert a null Value into SlotTracker!"); - assert(!V->getType()->isVoidTy() && "Doesn't need a slot!"); - assert(!V->hasName() && "Doesn't need a slot!"); - - unsigned DestSlot = mNext++; - mMap[V] = DestSlot; - - ST_DEBUG(" Inserting value [" << V->getType() << "] = " << V << " slot=" << - DestSlot << " ["); - // G = Global, F = Function, A = Alias, o = other - ST_DEBUG((isa(V) ? 'G' : - (isa(V) ? 'F' : - (isa(V) ? 'A' : 'o'))) << "]\n"); -} - -/// CreateSlot - Create a new slot for the specified value if it has no name. -void SlotTracker::CreateFunctionSlot(const Value *V) { - assert(!V->getType()->isVoidTy() && !V->hasName() && "Doesn't need a slot!"); - - unsigned DestSlot = fNext++; - fMap[V] = DestSlot; - - // G = Global, F = Function, o = other - ST_DEBUG(" Inserting value [" << V->getType() << "] = " << V << " slot=" << - DestSlot << " [o]\n"); -} - -/// CreateModuleSlot - Insert the specified MDNode* into the slot table. -void SlotTracker::CreateMetadataSlot(const MDNode *N) { - assert(N && "Can't insert a null Value into SlotTracker!"); - - unsigned DestSlot = mdnNext; - if (!mdnMap.insert(std::make_pair(N, DestSlot)).second) - return; - ++mdnNext; - - // Recursively add any MDNodes referenced by operands. - for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) - if (const MDNode *Op = dyn_cast_or_null(N->getOperand(i))) - CreateMetadataSlot(Op); -} - -void SlotTracker::CreateAttributeSetSlot(AttributeSet AS) { - assert(AS.hasAttributes(AttributeSet::FunctionIndex) && - "Doesn't need a slot!"); - - as_iterator I = asMap.find(AS); - if (I != asMap.end()) - return; - - unsigned DestSlot = asNext++; - asMap[AS] = DestSlot; -} - //===----------------------------------------------------------------------===// // AsmWriter Implementation //===----------------------------------------------------------------------===// Index: lib/IR/CMakeLists.txt =================================================================== --- lib/IR/CMakeLists.txt +++ lib/IR/CMakeLists.txt @@ -38,6 +38,7 @@ Pass.cpp PassManager.cpp PassRegistry.cpp + SlotTracker.cpp Statepoint.cpp Type.cpp TypeFinder.cpp Index: lib/IR/SlotTracker.cpp =================================================================== --- /dev/null +++ lib/IR/SlotTracker.cpp @@ -0,0 +1,275 @@ +//===-- SlotTracker.cpp - Implements the SlotTracker class ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the SlotTracker class. This class enumerates slot +// numbers for unnamed values, metadata nodes, and attribute sets. +// +//===----------------------------------------------------------------------===// + +#include "llvm/IR/SlotTracker.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Value.h" + +using namespace llvm; + +#if 0 +#define ST_DEBUG(X) dbgs() << X +#else +#define ST_DEBUG(X) +#endif + +// Module level constructor. Causes the contents of the Module (sans functions) +// to be added to the slot table. +SlotTracker::SlotTracker(const Module *M, bool ShouldInitializeAllMetadata) + : TheModule(M), TheFunction(nullptr), FunctionProcessed(false), + ShouldInitializeAllMetadata(ShouldInitializeAllMetadata), mNext(0), + fNext(0), mdnNext(0), asNext(0) {} + +// Function level constructor. Causes the contents of the Module and the one +// function provided to be added to the slot table. +SlotTracker::SlotTracker(const Function *F, bool ShouldInitializeAllMetadata) + : TheModule(F ? F->getParent() : nullptr), TheFunction(F), + FunctionProcessed(false), + ShouldInitializeAllMetadata(ShouldInitializeAllMetadata), mNext(0), + fNext(0), mdnNext(0), asNext(0) {} + +void SlotTracker::initialize() { + if (TheModule) { + processModule(); + TheModule = nullptr; ///< Prevent re-processing next time we're called. + } + + if (TheFunction && !FunctionProcessed) + processFunction(); +} + +// Iterate through all the global variables, functions, and global +// variable initializers and create slots for them. +void SlotTracker::processModule() { + ST_DEBUG("begin processModule!\n"); + + // Add all of the unnamed global variables to the value table. + for (Module::const_global_iterator I = TheModule->global_begin(), + E = TheModule->global_end(); I != E; ++I) { + if (!I->hasName()) + CreateModuleSlot(I); + } + + // Add metadata used by named metadata. + for (Module::const_named_metadata_iterator + I = TheModule->named_metadata_begin(), + E = TheModule->named_metadata_end(); I != E; ++I) { + const NamedMDNode *NMD = I; + for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) + CreateMetadataSlot(NMD->getOperand(i)); + } + + for (Module::const_iterator I = TheModule->begin(), E = TheModule->end(); + I != E; ++I) { + if (!I->hasName()) + // Add all the unnamed functions to the table. + CreateModuleSlot(I); + + if (ShouldInitializeAllMetadata) + processFunctionMetadata(*I); + + // Add all the function attributes to the table. + // FIXME: Add attributes of other objects? + AttributeSet FnAttrs = I->getAttributes().getFnAttributes(); + if (FnAttrs.hasAttributes(AttributeSet::FunctionIndex)) + CreateAttributeSetSlot(FnAttrs); + } + + ST_DEBUG("end processModule!\n"); +} + +// Process the arguments, basic blocks, and instructions of a function. +void SlotTracker::processFunction() { + ST_DEBUG("begin processFunction!\n"); + fNext = 0; + + // Add all the function arguments with no names. + for(Function::const_arg_iterator AI = TheFunction->arg_begin(), + AE = TheFunction->arg_end(); AI != AE; ++AI) + if (!AI->hasName()) + CreateFunctionSlot(AI); + + ST_DEBUG("Inserting Instructions:\n"); + + // Add all of the basic blocks and instructions with no names. + for (auto &BB : *TheFunction) { + if (!BB.hasName()) + CreateFunctionSlot(&BB); + + processFunctionMetadata(*TheFunction); + + for (auto &I : BB) { + if (!I.getType()->isVoidTy() && !I.hasName()) + CreateFunctionSlot(&I); + + // We allow direct calls to any llvm.foo function here, because the + // target may not be linked into the optimizer. + if (const CallInst *CI = dyn_cast(&I)) { + // Add all the call attributes to the table. + AttributeSet Attrs = CI->getAttributes().getFnAttributes(); + if (Attrs.hasAttributes(AttributeSet::FunctionIndex)) + CreateAttributeSetSlot(Attrs); + } else if (const InvokeInst *II = dyn_cast(&I)) { + // Add all the call attributes to the table. + AttributeSet Attrs = II->getAttributes().getFnAttributes(); + if (Attrs.hasAttributes(AttributeSet::FunctionIndex)) + CreateAttributeSetSlot(Attrs); + } + } + } + + FunctionProcessed = true; + + ST_DEBUG("end processFunction!\n"); +} + +void SlotTracker::processFunctionMetadata(const Function &F) { + SmallVector, 4> MDs; + for (auto &BB : F) { + F.getAllMetadata(MDs); + for (auto &MD : MDs) + CreateMetadataSlot(MD.second); + + for (auto &I : BB) + processInstructionMetadata(I); + } +} + +void SlotTracker::processInstructionMetadata(const Instruction &I) { + // Process metadata used directly by intrinsics. + if (const CallInst *CI = dyn_cast(&I)) + if (Function *F = CI->getCalledFunction()) + if (F->isIntrinsic()) + for (auto &Op : I.operands()) + if (auto *V = dyn_cast_or_null(Op)) + if (MDNode *N = dyn_cast(V->getMetadata())) + CreateMetadataSlot(N); + + // Process metadata attached to this instruction. + SmallVector, 4> MDs; + I.getAllMetadata(MDs); + for (auto &MD : MDs) + CreateMetadataSlot(MD.second); +} + +/// Clean up after incorporating a function. This is the only way to get out of +/// the function incorporation state that affects get*Slot/Create*Slot. Function +/// incorporation state is indicated by TheFunction != 0. +void SlotTracker::purgeFunction() { + ST_DEBUG("begin purgeFunction!\n"); + fMap.clear(); // Simply discard the function level map + TheFunction = nullptr; + FunctionProcessed = false; + ST_DEBUG("end purgeFunction!\n"); +} + +/// getGlobalSlot - Get the slot number of a global value. +int SlotTracker::getGlobalSlot(const GlobalValue *V) { + // Check for uninitialized state and do lazy initialization. + initialize(); + + // Find the value in the module map + ValueMap::iterator MI = mMap.find(V); + return MI == mMap.end() ? -1 : (int)MI->second; +} + +/// getMetadataSlot - Get the slot number of a MDNode. +int SlotTracker::getMetadataSlot(const MDNode *N) { + // Check for uninitialized state and do lazy initialization. + initialize(); + + // Find the MDNode in the module map + mdn_iterator MI = mdnMap.find(N); + return MI == mdnMap.end() ? -1 : (int)MI->second; +} + + +/// getLocalSlot - Get the slot number for a value that is local to a function. +int SlotTracker::getLocalSlot(const Value *V) { + assert(!isa(V) && "Can't get a constant or global slot with this!"); + + // Check for uninitialized state and do lazy initialization. + initialize(); + + ValueMap::iterator FI = fMap.find(V); + return FI == fMap.end() ? -1 : (int)FI->second; +} + +int SlotTracker::getAttributeGroupSlot(AttributeSet AS) { + // Check for uninitialized state and do lazy initialization. + initialize(); + + // Find the AttributeSet in the module map. + as_iterator AI = asMap.find(AS); + return AI == asMap.end() ? -1 : (int)AI->second; +} + +/// CreateModuleSlot - Insert the specified GlobalValue* into the slot table. +void SlotTracker::CreateModuleSlot(const GlobalValue *V) { + assert(V && "Can't insert a null Value into SlotTracker!"); + assert(!V->getType()->isVoidTy() && "Doesn't need a slot!"); + assert(!V->hasName() && "Doesn't need a slot!"); + + unsigned DestSlot = mNext++; + mMap[V] = DestSlot; + + ST_DEBUG(" Inserting value [" << V->getType() << "] = " << V << " slot=" << + DestSlot << " ["); + // G = Global, F = Function, A = Alias, o = other + ST_DEBUG((isa(V) ? 'G' : + (isa(V) ? 'F' : + (isa(V) ? 'A' : 'o'))) << "]\n"); +} + +/// CreateSlot - Create a new slot for the specified value if it has no name. +void SlotTracker::CreateFunctionSlot(const Value *V) { + assert(!V->getType()->isVoidTy() && !V->hasName() && "Doesn't need a slot!"); + + unsigned DestSlot = fNext++; + fMap[V] = DestSlot; + + // G = Global, F = Function, o = other + ST_DEBUG(" Inserting value [" << V->getType() << "] = " << V << " slot=" << + DestSlot << " [o]\n"); +} + +/// CreateModuleSlot - Insert the specified MDNode* into the slot table. +void SlotTracker::CreateMetadataSlot(const MDNode *N) { + assert(N && "Can't insert a null Value into SlotTracker!"); + + unsigned DestSlot = mdnNext; + if (!mdnMap.insert(std::make_pair(N, DestSlot)).second) + return; + ++mdnNext; + + // Recursively add any MDNodes referenced by operands. + for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) + if (const MDNode *Op = dyn_cast_or_null(N->getOperand(i))) + CreateMetadataSlot(Op); +} + +void SlotTracker::CreateAttributeSetSlot(AttributeSet AS) { + assert(AS.hasAttributes(AttributeSet::FunctionIndex) && + "Doesn't need a slot!"); + + as_iterator I = asMap.find(AS); + if (I != asMap.end()) + return; + + unsigned DestSlot = asNext++; + asMap[AS] = DestSlot; +}