blob: 9856ae6f9c1682dbe251b05baf52998ffc4df5ec [file]
//===- Utils.h - IR2Vec/MIR2Vec Tool Classes ----------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file contains the IR2VecTool and MIR2VecTool class definitions for
/// the llvm-ir2vec embedding generation tool.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_TOOLS_LLVM_IR2VEC_UTILS_UTILS_H
#define LLVM_TOOLS_LLVM_IR2VEC_UTILS_UTILS_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/Analysis/IR2Vec.h"
#include "llvm/CodeGen/MIR2Vec.h"
#include "llvm/CodeGen/MIRParser/MIRParser.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/PassInstrumentation.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/Type.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/WithColor.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
#include <memory>
#include <string>
#include <vector>
#define DEBUG_TYPE "ir2vec"
namespace llvm {
/// Tool name for error reporting
static const char *ToolName = "llvm-ir2vec";
/// Specifies the granularity at which embeddings are generated.
enum EmbeddingLevel {
InstructionLevel, // Generate instruction-level embeddings
BasicBlockLevel, // Generate basic block-level embeddings
FunctionLevel // Generate function-level embeddings
};
/// Represents a single knowledge graph triplet (Head, Relation, Tail)
/// where indices reference entities in an EntityList
struct Triplet {
unsigned Head = 0; ///< Index of the head entity in the entity list
unsigned Tail = 0; ///< Index of the tail entity in the entity list
unsigned Relation = 0; ///< Relation type (see RelationType enum)
};
/// Result structure containing all generated triplets and metadata
struct TripletResult {
unsigned MaxRelation =
0; ///< Highest relation index used (for ArgRelation + N)
std::vector<Triplet> Triplets; ///< Collection of all generated triplets
};
/// Entity mappings: [entity_name]
using EntityList = std::vector<std::string>;
using FuncEmbMap = DenseMap<const Function *, ir2vec::Embedding>;
namespace ir2vec {
/// Relation types for triplet generation
enum RelationType {
TypeRelation = 0, ///< Instruction to type relationship
NextRelation = 1, ///< Sequential instruction relationship
ArgRelation = 2 ///< Instruction to operand relationship (ArgRelation + N)
};
/// Load an IR2Vec vocabulary from a JSON file on disk.
Expected<std::shared_ptr<Vocabulary>> loadVocabulary(StringRef VocabPath);
/// Helper class for collecting IR triplets and generating embeddings
class IR2VecTool {
private:
Module &M;
ModuleAnalysisManager MAM;
/// \note The API around vocab object is not thread-safe.
/// Specifically, calling setVocabulary() on an instance while
/// another thread reading the Vocab object with the same instance
/// can cause a data race on this internal shared_ptr<Vocabulary> member.
std::shared_ptr<Vocabulary> Vocab;
public:
explicit IR2VecTool(Module &M) : M(M) {}
/// Creates the embedding object for downstream embedding streaming
Expected<std::unique_ptr<Embedder>>
createIR2VecEmbedder(const Function &F, IR2VecKind Kind) const;
/// Sets the vocabulary for this tool instance.
/// This allows sharing the same vocabulary instance across multiple
/// IR2VecTool instances, which is useful for generating embeddings for
/// multiple functions without needing to reload the vocabulary each time.
Error setVocabulary(std::shared_ptr<Vocabulary> V);
/// Generate triplets for a single function
/// Returns a TripletResult with:
/// - Triplets: vector of all (subject, object, relation) tuples
/// - MaxRelation: highest Arg relation ID used, or NextRelation if none
TripletResult generateTriplets(const Function &F) const;
/// Get triplets for the entire module
TripletResult generateTriplets() const;
/// Collect triplets for the module and dump output to stream
/// Output format: MAX_RELATION=N header followed by relationships
void writeTripletsToStream(raw_ostream &OS) const;
/// Generate entity mappings for the entire vocabulary
/// Returns EntityList containing all entity strings
static EntityList collectEntityMappings();
/// Dump entity ID to string mappings
static void writeEntitiesToStream(raw_ostream &OS);
// Get embedding for a single function
Expected<Embedding> getFunctionEmbedding(const Function &F,
IR2VecKind Kind) const;
/// Get embeddings for all functions in the module
Expected<FuncEmbMap> getFunctionEmbeddingsMap(IR2VecKind Kind) const;
/// Get embeddings for all basic blocks in a function
Expected<BBEmbeddingsMap> getBBEmbeddingsMap(const Function &F,
IR2VecKind Kind) const;
/// Get embeddings for all instructions in a function
Expected<InstEmbeddingsMap> getInstEmbeddingsMap(const Function &F,
IR2VecKind Kind) const;
/// Generate embeddings for the entire module
void writeEmbeddingsToStream(raw_ostream &OS, EmbeddingLevel Level) const;
/// Generate embeddings for a single function
void writeEmbeddingsToStream(const Function &F, raw_ostream &OS,
EmbeddingLevel Level) const;
};
} // namespace ir2vec
namespace mir2vec {
/// Relation types for MIR2Vec triplet generation
enum MIRRelationType {
MIRNextRelation = 0, ///< Sequential instruction relationship
MIRArgRelation = 1 ///< Instruction to operand relationship (ArgRelation + N)
};
/// Helper class for MIR2Vec embedding generation
class MIR2VecTool {
private:
MachineModuleInfo &MMI;
std::unique_ptr<MIRVocabulary> Vocab;
public:
explicit MIR2VecTool(MachineModuleInfo &MMI) : MMI(MMI) {}
/// Initialize MIR2Vec vocabulary from file (for embeddings generation)
bool initializeVocabulary(const Module &M);
/// Initialize vocabulary with layout information only.
/// This creates a minimal vocabulary with correct layout but no actual
/// embeddings. Sufficient for generating training data and entity mappings.
///
/// Note: Requires target-specific information from the first machine function
/// to determine the vocabulary layout (number of opcodes, register classes).
///
/// FIXME: Use --target option to get target info directly, avoiding the need
/// to parse machine functions for pre-training operations.
bool initializeVocabularyForLayout(const Module &M);
/// Get triplets for a single machine function
/// Returns TripletResult containing MaxRelation and vector of Triplets
TripletResult generateTriplets(const MachineFunction &MF) const;
/// Get triplets for the entire module
/// Returns TripletResult containing aggregated MaxRelation and all Triplets
TripletResult generateTriplets(const Module &M) const;
/// Collect triplets for the module and write to output stream
/// Output format: MAX_RELATION=N header followed by relationships
void writeTripletsToStream(const Module &M, raw_ostream &OS) const;
/// Generate entity mappings for the entire vocabulary
EntityList collectEntityMappings() const;
/// Generate entity mappings and write to output stream
void writeEntitiesToStream(raw_ostream &OS) const;
/// Generate embeddings for all machine functions in the module
void writeEmbeddingsToStream(const Module &M, raw_ostream &OS,
EmbeddingLevel Level) const;
/// Generate embeddings for a specific machine function
void writeEmbeddingsToStream(MachineFunction &MF, raw_ostream &OS,
EmbeddingLevel Level) const;
/// Get the MIR vocabulary instance
const MIRVocabulary *getVocabulary() const { return Vocab.get(); }
};
/// Helper structure to hold MIR context
struct MIRContext {
LLVMContext Context; // CRITICAL: Must be first for proper destruction order
std::unique_ptr<Module> M;
std::unique_ptr<MachineModuleInfo> MMI;
std::unique_ptr<TargetMachine> TM;
};
} // namespace mir2vec
} // namespace llvm
#endif // LLVM_TOOLS_LLVM_IR2VEC_UTILS_UTILS_H