181ad6265SDimitry Andric //===- DirectX/DXILWriter/ValueEnumerator.h - Number values -----*- C++ -*-===// 281ad6265SDimitry Andric // 381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 681ad6265SDimitry Andric // 781ad6265SDimitry Andric //===----------------------------------------------------------------------===// 881ad6265SDimitry Andric // 981ad6265SDimitry Andric // This class gives values and types Unique ID's. 1081ad6265SDimitry Andric // Forked from lib/Bitcode/Writer 1181ad6265SDimitry Andric // 1281ad6265SDimitry Andric //===----------------------------------------------------------------------===// 1381ad6265SDimitry Andric 1481ad6265SDimitry Andric #ifndef LLVM_DXILWRITER_VALUEENUMERATOR_H 1581ad6265SDimitry Andric #define LLVM_DXILWRITER_VALUEENUMERATOR_H 1681ad6265SDimitry Andric 1781ad6265SDimitry Andric #include "llvm/ADT/ArrayRef.h" 1881ad6265SDimitry Andric #include "llvm/ADT/DenseMap.h" 1981ad6265SDimitry Andric #include "llvm/ADT/UniqueVector.h" 2081ad6265SDimitry Andric #include "llvm/IR/Attributes.h" 2181ad6265SDimitry Andric #include "llvm/IR/UseListOrder.h" 2281ad6265SDimitry Andric #include <cassert> 2381ad6265SDimitry Andric #include <cstdint> 2481ad6265SDimitry Andric #include <utility> 2581ad6265SDimitry Andric #include <vector> 2681ad6265SDimitry Andric 2781ad6265SDimitry Andric namespace llvm { 2881ad6265SDimitry Andric 2981ad6265SDimitry Andric class BasicBlock; 3081ad6265SDimitry Andric class Comdat; 3181ad6265SDimitry Andric class DIArgList; 3281ad6265SDimitry Andric class Function; 3381ad6265SDimitry Andric class Instruction; 3481ad6265SDimitry Andric class LocalAsMetadata; 3581ad6265SDimitry Andric class MDNode; 3681ad6265SDimitry Andric class Metadata; 3781ad6265SDimitry Andric class Module; 3881ad6265SDimitry Andric class NamedMDNode; 3981ad6265SDimitry Andric class raw_ostream; 4081ad6265SDimitry Andric class Type; 4181ad6265SDimitry Andric class Value; 4281ad6265SDimitry Andric class ValueSymbolTable; 4381ad6265SDimitry Andric 4481ad6265SDimitry Andric namespace dxil { 4581ad6265SDimitry Andric 4681ad6265SDimitry Andric class ValueEnumerator { 4781ad6265SDimitry Andric public: 4881ad6265SDimitry Andric using TypeList = std::vector<Type *>; 4981ad6265SDimitry Andric 5081ad6265SDimitry Andric // For each value, we remember its Value* and occurrence frequency. 5181ad6265SDimitry Andric using ValueList = std::vector<std::pair<const Value *, unsigned>>; 5281ad6265SDimitry Andric 5381ad6265SDimitry Andric /// Attribute groups as encoded in bitcode are almost AttributeSets, but they 5481ad6265SDimitry Andric /// include the AttributeList index, so we have to track that in our map. 5581ad6265SDimitry Andric using IndexAndAttrSet = std::pair<unsigned, AttributeSet>; 5681ad6265SDimitry Andric 5781ad6265SDimitry Andric UseListOrderStack UseListOrders; 5881ad6265SDimitry Andric 5981ad6265SDimitry Andric private: 6081ad6265SDimitry Andric using TypeMapType = DenseMap<Type *, unsigned>; 6181ad6265SDimitry Andric TypeMapType TypeMap; 6281ad6265SDimitry Andric TypeList Types; 6381ad6265SDimitry Andric 6481ad6265SDimitry Andric using ValueMapType = DenseMap<const Value *, unsigned>; 6581ad6265SDimitry Andric ValueMapType ValueMap; 6681ad6265SDimitry Andric ValueList Values; 6781ad6265SDimitry Andric 6881ad6265SDimitry Andric using ComdatSetType = UniqueVector<const Comdat *>; 6981ad6265SDimitry Andric ComdatSetType Comdats; 7081ad6265SDimitry Andric 7181ad6265SDimitry Andric std::vector<const Metadata *> MDs; 7281ad6265SDimitry Andric std::vector<const Metadata *> FunctionMDs; 7381ad6265SDimitry Andric 7481ad6265SDimitry Andric /// Index of information about a piece of metadata. 7581ad6265SDimitry Andric struct MDIndex { 7681ad6265SDimitry Andric unsigned F = 0; ///< The ID of the function for this metadata, if any. 7781ad6265SDimitry Andric unsigned ID = 0; ///< The implicit ID of this metadata in bitcode. 7881ad6265SDimitry Andric 7981ad6265SDimitry Andric MDIndex() = default; 8081ad6265SDimitry Andric explicit MDIndex(unsigned F) : F(F) {} 8181ad6265SDimitry Andric 8281ad6265SDimitry Andric /// Check if this has a function tag, and it's different from NewF. 8381ad6265SDimitry Andric bool hasDifferentFunction(unsigned NewF) const { return F && F != NewF; } 8481ad6265SDimitry Andric 8581ad6265SDimitry Andric /// Fetch the MD this references out of the given metadata array. 8681ad6265SDimitry Andric const Metadata *get(ArrayRef<const Metadata *> MDs) const { 8781ad6265SDimitry Andric assert(ID && "Expected non-zero ID"); 8881ad6265SDimitry Andric assert(ID <= MDs.size() && "Expected valid ID"); 8981ad6265SDimitry Andric return MDs[ID - 1]; 9081ad6265SDimitry Andric } 9181ad6265SDimitry Andric }; 9281ad6265SDimitry Andric 9381ad6265SDimitry Andric using MetadataMapType = DenseMap<const Metadata *, MDIndex>; 9481ad6265SDimitry Andric MetadataMapType MetadataMap; 9581ad6265SDimitry Andric 9681ad6265SDimitry Andric /// Range of metadata IDs, as a half-open range. 9781ad6265SDimitry Andric struct MDRange { 9881ad6265SDimitry Andric unsigned First = 0; 9981ad6265SDimitry Andric unsigned Last = 0; 10081ad6265SDimitry Andric 10181ad6265SDimitry Andric /// Number of strings in the prefix of the metadata range. 10281ad6265SDimitry Andric unsigned NumStrings = 0; 10381ad6265SDimitry Andric 10481ad6265SDimitry Andric MDRange() = default; 10581ad6265SDimitry Andric explicit MDRange(unsigned First) : First(First) {} 10681ad6265SDimitry Andric }; 10781ad6265SDimitry Andric SmallDenseMap<unsigned, MDRange, 1> FunctionMDInfo; 10881ad6265SDimitry Andric 10981ad6265SDimitry Andric using AttributeGroupMapType = DenseMap<IndexAndAttrSet, unsigned>; 11081ad6265SDimitry Andric AttributeGroupMapType AttributeGroupMap; 11181ad6265SDimitry Andric std::vector<IndexAndAttrSet> AttributeGroups; 11281ad6265SDimitry Andric 11381ad6265SDimitry Andric using AttributeListMapType = DenseMap<AttributeList, unsigned>; 11481ad6265SDimitry Andric AttributeListMapType AttributeListMap; 11581ad6265SDimitry Andric std::vector<AttributeList> AttributeLists; 11681ad6265SDimitry Andric 11781ad6265SDimitry Andric /// GlobalBasicBlockIDs - This map memoizes the basic block ID's referenced by 11881ad6265SDimitry Andric /// the "getGlobalBasicBlockID" method. 11981ad6265SDimitry Andric mutable DenseMap<const BasicBlock *, unsigned> GlobalBasicBlockIDs; 12081ad6265SDimitry Andric 12181ad6265SDimitry Andric using InstructionMapType = DenseMap<const Instruction *, unsigned>; 12281ad6265SDimitry Andric InstructionMapType InstructionMap; 12381ad6265SDimitry Andric unsigned InstructionCount; 12481ad6265SDimitry Andric 12581ad6265SDimitry Andric /// BasicBlocks - This contains all the basic blocks for the currently 12681ad6265SDimitry Andric /// incorporated function. Their reverse mapping is stored in ValueMap. 12781ad6265SDimitry Andric std::vector<const BasicBlock *> BasicBlocks; 12881ad6265SDimitry Andric 12981ad6265SDimitry Andric /// When a function is incorporated, this is the size of the Values list 13081ad6265SDimitry Andric /// before incorporation. 13181ad6265SDimitry Andric unsigned NumModuleValues; 13281ad6265SDimitry Andric 13381ad6265SDimitry Andric /// When a function is incorporated, this is the size of the Metadatas list 13481ad6265SDimitry Andric /// before incorporation. 13581ad6265SDimitry Andric unsigned NumModuleMDs = 0; 13681ad6265SDimitry Andric unsigned NumMDStrings = 0; 13781ad6265SDimitry Andric 13881ad6265SDimitry Andric unsigned FirstFuncConstantID; 13981ad6265SDimitry Andric unsigned FirstInstID; 14081ad6265SDimitry Andric 14181ad6265SDimitry Andric public: 14281ad6265SDimitry Andric ValueEnumerator(const Module &M, Type *PrefixType); 14381ad6265SDimitry Andric ValueEnumerator(const ValueEnumerator &) = delete; 14481ad6265SDimitry Andric ValueEnumerator &operator=(const ValueEnumerator &) = delete; 14581ad6265SDimitry Andric 14681ad6265SDimitry Andric void dump() const; 14781ad6265SDimitry Andric void print(raw_ostream &OS, const ValueMapType &Map, const char *Name) const; 14881ad6265SDimitry Andric void print(raw_ostream &OS, const MetadataMapType &Map, 14981ad6265SDimitry Andric const char *Name) const; 15081ad6265SDimitry Andric 15181ad6265SDimitry Andric unsigned getValueID(const Value *V) const; 15281ad6265SDimitry Andric 15381ad6265SDimitry Andric unsigned getMetadataID(const Metadata *MD) const { 15481ad6265SDimitry Andric auto ID = getMetadataOrNullID(MD); 15581ad6265SDimitry Andric assert(ID != 0 && "Metadata not in slotcalculator!"); 15681ad6265SDimitry Andric return ID - 1; 15781ad6265SDimitry Andric } 15881ad6265SDimitry Andric 15981ad6265SDimitry Andric unsigned getMetadataOrNullID(const Metadata *MD) const { 16081ad6265SDimitry Andric return MetadataMap.lookup(MD).ID; 16181ad6265SDimitry Andric } 16281ad6265SDimitry Andric 16381ad6265SDimitry Andric unsigned numMDs() const { return MDs.size(); } 16481ad6265SDimitry Andric 16581ad6265SDimitry Andric unsigned getTypeID(Type *T) const { 16681ad6265SDimitry Andric TypeMapType::const_iterator I = TypeMap.find(T); 16781ad6265SDimitry Andric assert(I != TypeMap.end() && "Type not in ValueEnumerator!"); 16881ad6265SDimitry Andric return I->second - 1; 16981ad6265SDimitry Andric } 17081ad6265SDimitry Andric 17181ad6265SDimitry Andric unsigned getInstructionID(const Instruction *I) const; 17281ad6265SDimitry Andric void setInstructionID(const Instruction *I); 17381ad6265SDimitry Andric 17481ad6265SDimitry Andric unsigned getAttributeListID(AttributeList PAL) const { 17581ad6265SDimitry Andric if (PAL.isEmpty()) 17681ad6265SDimitry Andric return 0; // Null maps to zero. 17781ad6265SDimitry Andric AttributeListMapType::const_iterator I = AttributeListMap.find(PAL); 17881ad6265SDimitry Andric assert(I != AttributeListMap.end() && "Attribute not in ValueEnumerator!"); 17981ad6265SDimitry Andric return I->second; 18081ad6265SDimitry Andric } 18181ad6265SDimitry Andric 18281ad6265SDimitry Andric unsigned getAttributeGroupID(IndexAndAttrSet Group) const { 18381ad6265SDimitry Andric if (!Group.second.hasAttributes()) 18481ad6265SDimitry Andric return 0; // Null maps to zero. 18581ad6265SDimitry Andric AttributeGroupMapType::const_iterator I = AttributeGroupMap.find(Group); 18681ad6265SDimitry Andric assert(I != AttributeGroupMap.end() && "Attribute not in ValueEnumerator!"); 18781ad6265SDimitry Andric return I->second; 18881ad6265SDimitry Andric } 18981ad6265SDimitry Andric 19081ad6265SDimitry Andric /// getFunctionConstantRange - Return the range of values that corresponds to 19181ad6265SDimitry Andric /// function-local constants. 19281ad6265SDimitry Andric void getFunctionConstantRange(unsigned &Start, unsigned &End) const { 19381ad6265SDimitry Andric Start = FirstFuncConstantID; 19481ad6265SDimitry Andric End = FirstInstID; 19581ad6265SDimitry Andric } 19681ad6265SDimitry Andric 19781ad6265SDimitry Andric const ValueList &getValues() const { return Values; } 19881ad6265SDimitry Andric 19981ad6265SDimitry Andric /// Check whether the current block has any metadata to emit. 20081ad6265SDimitry Andric bool hasMDs() const { return NumModuleMDs < MDs.size(); } 20181ad6265SDimitry Andric 20281ad6265SDimitry Andric /// Get the MDString metadata for this block. 20381ad6265SDimitry Andric ArrayRef<const Metadata *> getMDStrings() const { 204bdd1243dSDimitry Andric return ArrayRef(MDs).slice(NumModuleMDs, NumMDStrings); 20581ad6265SDimitry Andric } 20681ad6265SDimitry Andric 20781ad6265SDimitry Andric /// Get the non-MDString metadata for this block. 20881ad6265SDimitry Andric ArrayRef<const Metadata *> getNonMDStrings() const { 209bdd1243dSDimitry Andric return ArrayRef(MDs).slice(NumModuleMDs).slice(NumMDStrings); 21081ad6265SDimitry Andric } 21181ad6265SDimitry Andric 21281ad6265SDimitry Andric const TypeList &getTypes() const { return Types; } 21381ad6265SDimitry Andric 21481ad6265SDimitry Andric const std::vector<const BasicBlock *> &getBasicBlocks() const { 21581ad6265SDimitry Andric return BasicBlocks; 21681ad6265SDimitry Andric } 21781ad6265SDimitry Andric 21881ad6265SDimitry Andric const std::vector<AttributeList> &getAttributeLists() const { 21981ad6265SDimitry Andric return AttributeLists; 22081ad6265SDimitry Andric } 22181ad6265SDimitry Andric 22281ad6265SDimitry Andric const std::vector<IndexAndAttrSet> &getAttributeGroups() const { 22381ad6265SDimitry Andric return AttributeGroups; 22481ad6265SDimitry Andric } 22581ad6265SDimitry Andric 22681ad6265SDimitry Andric const ComdatSetType &getComdats() const { return Comdats; } 22781ad6265SDimitry Andric unsigned getComdatID(const Comdat *C) const; 22881ad6265SDimitry Andric 22981ad6265SDimitry Andric /// getGlobalBasicBlockID - This returns the function-specific ID for the 23081ad6265SDimitry Andric /// specified basic block. This is relatively expensive information, so it 23181ad6265SDimitry Andric /// should only be used by rare constructs such as address-of-label. 23281ad6265SDimitry Andric unsigned getGlobalBasicBlockID(const BasicBlock *BB) const; 23381ad6265SDimitry Andric 23481ad6265SDimitry Andric /// incorporateFunction/purgeFunction - If you'd like to deal with a function, 23581ad6265SDimitry Andric /// use these two methods to get its data into the ValueEnumerator! 23681ad6265SDimitry Andric void incorporateFunction(const Function &F); 23781ad6265SDimitry Andric 23881ad6265SDimitry Andric void purgeFunction(); 239*0fca6ea1SDimitry Andric uint64_t computeBitsRequiredForTypeIndices() const; 24081ad6265SDimitry Andric 24181ad6265SDimitry Andric void EnumerateType(Type *T); 24281ad6265SDimitry Andric 24381ad6265SDimitry Andric private: 24481ad6265SDimitry Andric 24581ad6265SDimitry Andric /// Reorder the reachable metadata. 24681ad6265SDimitry Andric /// 24781ad6265SDimitry Andric /// This is not just an optimization, but is mandatory for emitting MDString 24881ad6265SDimitry Andric /// correctly. 24981ad6265SDimitry Andric void organizeMetadata(); 25081ad6265SDimitry Andric 25181ad6265SDimitry Andric /// Drop the function tag from the transitive operands of the given node. 25281ad6265SDimitry Andric void dropFunctionFromMetadata(MetadataMapType::value_type &FirstMD); 25381ad6265SDimitry Andric 25481ad6265SDimitry Andric /// Incorporate the function metadata. 25581ad6265SDimitry Andric /// 25681ad6265SDimitry Andric /// This should be called before enumerating LocalAsMetadata for the 25781ad6265SDimitry Andric /// function. 25881ad6265SDimitry Andric void incorporateFunctionMetadata(const Function &F); 25981ad6265SDimitry Andric 26081ad6265SDimitry Andric /// Enumerate a single instance of metadata with the given function tag. 26181ad6265SDimitry Andric /// 26281ad6265SDimitry Andric /// If \c MD has already been enumerated, check that \c F matches its 26381ad6265SDimitry Andric /// function tag. If not, call \a dropFunctionFromMetadata(). 26481ad6265SDimitry Andric /// 26581ad6265SDimitry Andric /// Otherwise, mark \c MD as visited. Assign it an ID, or just return it if 26681ad6265SDimitry Andric /// it's an \a MDNode. 26781ad6265SDimitry Andric const MDNode *enumerateMetadataImpl(unsigned F, const Metadata *MD); 26881ad6265SDimitry Andric 26981ad6265SDimitry Andric unsigned getMetadataFunctionID(const Function *F) const; 27081ad6265SDimitry Andric 27181ad6265SDimitry Andric /// Enumerate reachable metadata in (almost) post-order. 27281ad6265SDimitry Andric /// 27381ad6265SDimitry Andric /// Enumerate all the metadata reachable from MD. We want to minimize the 27481ad6265SDimitry Andric /// cost of reading bitcode records, and so the primary consideration is that 27581ad6265SDimitry Andric /// operands of uniqued nodes are resolved before the nodes are read. This 27681ad6265SDimitry Andric /// avoids re-uniquing them on the context and factors away RAUW support. 27781ad6265SDimitry Andric /// 27881ad6265SDimitry Andric /// This algorithm guarantees that subgraphs of uniqued nodes are in 27981ad6265SDimitry Andric /// post-order. Distinct subgraphs reachable only from a single uniqued node 28081ad6265SDimitry Andric /// will be in post-order. 28181ad6265SDimitry Andric /// 28281ad6265SDimitry Andric /// \note The relative order of a distinct and uniqued node is irrelevant. 28381ad6265SDimitry Andric /// \a organizeMetadata() will later partition distinct nodes ahead of 28481ad6265SDimitry Andric /// uniqued ones. 28581ad6265SDimitry Andric ///{ 28681ad6265SDimitry Andric void EnumerateMetadata(const Function *F, const Metadata *MD); 28781ad6265SDimitry Andric void EnumerateMetadata(unsigned F, const Metadata *MD); 28881ad6265SDimitry Andric ///} 28981ad6265SDimitry Andric 29081ad6265SDimitry Andric void EnumerateFunctionLocalMetadata(const Function &F, 29181ad6265SDimitry Andric const LocalAsMetadata *Local); 29281ad6265SDimitry Andric void EnumerateFunctionLocalMetadata(unsigned F, const LocalAsMetadata *Local); 29381ad6265SDimitry Andric void EnumerateFunctionLocalListMetadata(const Function &F, 29481ad6265SDimitry Andric const DIArgList *ArgList); 29581ad6265SDimitry Andric void EnumerateFunctionLocalListMetadata(unsigned F, const DIArgList *Arglist); 29681ad6265SDimitry Andric void EnumerateNamedMDNode(const NamedMDNode *NMD); 29781ad6265SDimitry Andric void EnumerateValue(const Value *V); 29881ad6265SDimitry Andric void EnumerateOperandType(const Value *V); 29981ad6265SDimitry Andric void EnumerateAttributes(AttributeList PAL); 30081ad6265SDimitry Andric 30181ad6265SDimitry Andric void EnumerateValueSymbolTable(const ValueSymbolTable &ST); 30281ad6265SDimitry Andric void EnumerateNamedMetadata(const Module &M); 30381ad6265SDimitry Andric }; 30481ad6265SDimitry Andric 30581ad6265SDimitry Andric } // end namespace dxil 30681ad6265SDimitry Andric } // end namespace llvm 30781ad6265SDimitry Andric 30881ad6265SDimitry Andric #endif // LLVM_DXILWRITER_VALUEENUMERATOR_H 309