Index: include/llvm/AsmParser/Parser.h =================================================================== --- include/llvm/AsmParser/Parser.h +++ include/llvm/AsmParser/Parser.h @@ -18,54 +18,66 @@ namespace llvm { +class LLVMContext; class Module; +struct SlotMapping; class SMDiagnostic; -class LLVMContext; /// This function is the main interface to the LLVM Assembly Parser. It parses /// an ASCII file that (presumably) contains LLVM Assembly code. It returns a /// Module (intermediate representation) with the corresponding features. Note /// that this does not verify that the generated Module is valid, so you should /// run the verifier after parsing the file to check that it is okay. -/// @brief Parse LLVM Assembly from a file -/// @param Filename The name of the file to parse -/// @param Error Error result info. -/// @param Context Context in which to allocate globals info. +/// \brief Parse LLVM Assembly from a file +/// \param Filename The name of the file to parse +/// \param Error Error result info. +/// \param Context Context in which to allocate globals info. +/// \param Mapping The optional slot mapping that will be initialized during +/// parsing. std::unique_ptr parseAssemblyFile(StringRef Filename, SMDiagnostic &Error, - LLVMContext &Context); + LLVMContext &Context, + SlotMapping *Mapping = nullptr); /// The function is a secondary interface to the LLVM Assembly Parser. It parses /// an ASCII string that (presumably) contains LLVM Assembly code. It returns a /// Module (intermediate representation) with the corresponding features. Note /// that this does not verify that the generated Module is valid, so you should /// run the verifier after parsing the file to check that it is okay. -/// @brief Parse LLVM Assembly from a string -/// @param AsmString The string containing assembly -/// @param Error Error result info. -/// @param Context Context in which to allocate globals info. +/// \brief Parse LLVM Assembly from a string +/// \param AsmString The string containing assembly +/// \param Error Error result info. +/// \param Context Context in which to allocate globals info. +/// \param Mapping The optional slot mapping that will be initialized during +/// parsing. std::unique_ptr parseAssemblyString(StringRef AsmString, SMDiagnostic &Error, - LLVMContext &Context); + LLVMContext &Context, + SlotMapping *Mapping = nullptr); /// parseAssemblyFile and parseAssemblyString are wrappers around this function. -/// @brief Parse LLVM Assembly from a MemoryBuffer. -/// @param F The MemoryBuffer containing assembly -/// @param Err Error result info. -/// @param Context Context in which to allocate globals info. +/// \brief Parse LLVM Assembly from a MemoryBuffer. +/// \param F The MemoryBuffer containing assembly +/// \param Err Error result info. +/// \param Mapping The optional slot mapping that will be initialized during +/// parsing. std::unique_ptr parseAssembly(MemoryBufferRef F, SMDiagnostic &Err, - LLVMContext &Context); + LLVMContext &Context, + SlotMapping *Mapping = nullptr); /// This function is the low-level interface to the LLVM Assembly Parser. /// This is kept as an independent function instead of being inlined into /// parseAssembly for the convenience of interactive users that want to add /// recently parsed bits to an existing module. /// -/// @param F The MemoryBuffer containing assembly -/// @param M The module to add data to. -/// @param Err Error result info. -/// @return true on error. -bool parseAssemblyInto(MemoryBufferRef F, Module &M, SMDiagnostic &Err); +/// \param F The MemoryBuffer containing assembly +/// \param M The module to add data to. +/// \param Err Error result info. +/// \param Mapping The optional slot mapping that will be initialized during +/// parsing. +/// \return true on error. +bool parseAssemblyInto(MemoryBufferRef F, Module &M, SMDiagnostic &Err, + SlotMapping *Mapping = nullptr); } // End llvm namespace Index: include/llvm/AsmParser/SlotMapping.h =================================================================== --- /dev/null +++ include/llvm/AsmParser/SlotMapping.h @@ -0,0 +1,34 @@ +//===-- SlotMapping.h - Slot number mapping 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 SlotMapping class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ASMPARSER_SLOTMAPPING_H +#define LLVM_ASMPARSER_SLOTMAPPING_H + +#include +#include + +namespace llvm { + +class GlobalValue; +class MDNode; + +/// This class contains the mapping from the slot numbers to unnamed metadata +/// nodes and global values. +struct SlotMapping { + std::vector NumberedGlobalValues; + std::map NumberedMetadata; +}; + +} // end namespace llvm + +#endif Index: lib/AsmParser/LLParser.h =================================================================== --- lib/AsmParser/LLParser.h +++ lib/AsmParser/LLParser.h @@ -37,6 +37,7 @@ class Comdat; class MDString; class MDNode; + struct SlotMapping; class StructType; /// ValID - Represents a reference of a definition of some sort with no type. @@ -87,6 +88,7 @@ LLVMContext &Context; LLLexer Lex; Module *M; + SlotMapping *Mapping; // Instruction metadata resolution. Each instruction can have a list of // MDRef info associated with them. @@ -135,9 +137,10 @@ std::map NumberedAttrBuilders; public: - LLParser(StringRef F, SourceMgr &SM, SMDiagnostic &Err, Module *m) - : Context(m->getContext()), Lex(F, SM, Err, m->getContext()), M(m), - BlockAddressPFS(nullptr) {} + LLParser(StringRef F, SourceMgr &SM, SMDiagnostic &Err, Module *M, + SlotMapping *Mapping = nullptr) + : Context(M->getContext()), Lex(F, SM, Err, M->getContext()), M(M), + Mapping(Mapping), BlockAddressPFS(nullptr) {} bool Run(); LLVMContext &getContext() { return Context; } @@ -151,6 +154,10 @@ return Error(Lex.getLoc(), Msg); } + /// Initialize the slot mapping using the global value and metadata node + /// number mappings that were created during parsing. + void constructSlotMapping(); + /// GetGlobalVal - Get a value with the specified name or ID, creating a /// forward reference record if needed. This can return null if the value /// exists but does not have the right type. Index: lib/AsmParser/LLParser.cpp =================================================================== --- lib/AsmParser/LLParser.cpp +++ lib/AsmParser/LLParser.cpp @@ -13,6 +13,7 @@ #include "LLParser.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/AsmParser/SlotMapping.h" #include "llvm/IR/AutoUpgrade.h" #include "llvm/IR/CallingConv.h" #include "llvm/IR/Constants.h" @@ -161,9 +162,19 @@ UpgradeDebugInfo(*M); + constructSlotMapping(); + return false; } +void LLParser::constructSlotMapping() { + if (!Mapping) + return; + for (const auto &N : NumberedMetadata) + Mapping->NumberedMetadata.insert(std::make_pair(N.first, N.second.get())); + Mapping->NumberedGlobalValues = NumberedVals; +} + //===----------------------------------------------------------------------===// // Top-Level Entities //===----------------------------------------------------------------------===// Index: lib/AsmParser/Parser.cpp =================================================================== --- lib/AsmParser/Parser.cpp +++ lib/AsmParser/Parser.cpp @@ -22,21 +22,23 @@ #include using namespace llvm; -bool llvm::parseAssemblyInto(MemoryBufferRef F, Module &M, SMDiagnostic &Err) { +bool llvm::parseAssemblyInto(MemoryBufferRef F, Module &M, SMDiagnostic &Err, + SlotMapping *Mapping) { SourceMgr SM; std::unique_ptr Buf = MemoryBuffer::getMemBuffer(F); SM.AddNewSourceBuffer(std::move(Buf), SMLoc()); - return LLParser(F.getBuffer(), SM, Err, &M).Run(); + return LLParser(F.getBuffer(), SM, Err, &M, Mapping).Run(); } std::unique_ptr llvm::parseAssembly(MemoryBufferRef F, SMDiagnostic &Err, - LLVMContext &Context) { + LLVMContext &Context, + SlotMapping *Mapping) { std::unique_ptr M = make_unique(F.getBufferIdentifier(), Context); - if (parseAssemblyInto(F, *M, Err)) + if (parseAssemblyInto(F, *M, Err, Mapping)) return nullptr; return M; @@ -44,7 +46,8 @@ std::unique_ptr llvm::parseAssemblyFile(StringRef Filename, SMDiagnostic &Err, - LLVMContext &Context) { + LLVMContext &Context, + SlotMapping *Mapping) { ErrorOr> FileOrErr = MemoryBuffer::getFileOrSTDIN(Filename); if (std::error_code EC = FileOrErr.getError()) { @@ -53,12 +56,14 @@ return nullptr; } - return parseAssembly(FileOrErr.get()->getMemBufferRef(), Err, Context); + return parseAssembly(FileOrErr.get()->getMemBufferRef(), Err, Context, + Mapping); } std::unique_ptr llvm::parseAssemblyString(StringRef AsmString, SMDiagnostic &Err, - LLVMContext &Context) { + LLVMContext &Context, + SlotMapping *Mapping) { MemoryBufferRef F(AsmString, ""); - return parseAssembly(F, Err, Context); + return parseAssembly(F, Err, Context, Mapping); } Index: unittests/AsmParser/AsmParserTest.cpp =================================================================== --- unittests/AsmParser/AsmParserTest.cpp +++ unittests/AsmParser/AsmParserTest.cpp @@ -9,6 +9,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/AsmParser/Parser.h" +#include "llvm/AsmParser/SlotMapping.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/Support/SourceMgr.h" @@ -44,4 +45,23 @@ #endif #endif +TEST(AsmParserTest, SlotMappingTest) { + LLVMContext &Ctx = getGlobalContext(); + StringRef Source = "@0 = global i32 0\n !0 = !{}\n !42 = !{i32 42}"; + SMDiagnostic Error; + SlotMapping Mapping; + auto Mod = parseAssemblyString(Source, Error, Ctx, &Mapping); + + EXPECT_TRUE(Mod != nullptr); + EXPECT_TRUE(Error.getMessage().empty()); + + ASSERT_EQ(Mapping.NumberedGlobalValues.size(), size_t(1)); + EXPECT_TRUE(isa(Mapping.NumberedGlobalValues[0])); + + EXPECT_EQ(Mapping.NumberedMetadata.size(), size_t(2)); + EXPECT_EQ(Mapping.NumberedMetadata.count(0), size_t(1)); + EXPECT_EQ(Mapping.NumberedMetadata.count(42), size_t(1)); + EXPECT_EQ(Mapping.NumberedMetadata.count(1), size_t(0)); +} + } // end anonymous namespace