diff options
-rw-r--r-- | llvm/include/llvm/AsmParser/Parser.h | 5 | ||||
-rw-r--r-- | llvm/include/llvm/AsmParser/SlotMapping.h | 12 | ||||
-rw-r--r-- | llvm/lib/AsmParser/LLParser.cpp | 21 | ||||
-rw-r--r-- | llvm/lib/AsmParser/LLParser.h | 6 | ||||
-rw-r--r-- | llvm/lib/AsmParser/Parser.cpp | 4 | ||||
-rw-r--r-- | llvm/unittests/AsmParser/AsmParserTest.cpp | 36 |
6 files changed, 77 insertions, 7 deletions
diff --git a/llvm/include/llvm/AsmParser/Parser.h b/llvm/include/llvm/AsmParser/Parser.h index 9fe33603bc6..96a15c1ec45 100644 --- a/llvm/include/llvm/AsmParser/Parser.h +++ b/llvm/include/llvm/AsmParser/Parser.h @@ -85,8 +85,11 @@ bool parseAssemblyInto(MemoryBufferRef F, Module &M, SMDiagnostic &Err, /// The constant value can be any LLVM constant, including a constant /// expression. /// +/// \param Slots The optional slot mapping that will restore the parsing state +/// of the module. /// \return null on error. -Constant *parseConstantValue(StringRef Asm, SMDiagnostic &Err, const Module &M); +Constant *parseConstantValue(StringRef Asm, SMDiagnostic &Err, const Module &M, + const SlotMapping *Slots = nullptr); } // End llvm namespace diff --git a/llvm/include/llvm/AsmParser/SlotMapping.h b/llvm/include/llvm/AsmParser/SlotMapping.h index c5f61d25c3a..bd7e8fcad8b 100644 --- a/llvm/include/llvm/AsmParser/SlotMapping.h +++ b/llvm/include/llvm/AsmParser/SlotMapping.h @@ -14,6 +14,7 @@ #ifndef LLVM_ASMPARSER_SLOTMAPPING_H #define LLVM_ASMPARSER_SLOTMAPPING_H +#include "llvm/ADT/StringMap.h" #include "llvm/IR/TrackingMDRef.h" #include <map> #include <vector> @@ -21,12 +22,19 @@ namespace llvm { class GlobalValue; +class Type; -/// This struct contains the mapping from the slot numbers to unnamed metadata -/// nodes and global values. +/// This struct contains the mappings from the slot numbers to unnamed metadata +/// nodes, global values and types. It also contains the mapping for the named +/// types. +/// It can be used to save the parsing state of an LLVM IR module so that the +/// textual references to the values in the module can be parsed outside of the +/// module's source. struct SlotMapping { std::vector<GlobalValue *> GlobalValues; std::map<unsigned, TrackingMDNodeRef> MetadataNodes; + StringMap<Type *> NamedTypes; + std::map<unsigned, Type *> Types; }; } // end namespace llvm diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index 83bc33d0e6c..fc7fceb2a26 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -49,7 +49,9 @@ bool LLParser::Run() { ValidateEndOfModule(); } -bool LLParser::parseStandaloneConstantValue(Constant *&C) { +bool LLParser::parseStandaloneConstantValue(Constant *&C, + const SlotMapping *Slots) { + restoreParsingState(Slots); Lex.Lex(); Type *Ty = nullptr; @@ -60,6 +62,19 @@ bool LLParser::parseStandaloneConstantValue(Constant *&C) { return false; } +void LLParser::restoreParsingState(const SlotMapping *Slots) { + if (!Slots) + return; + NumberedVals = Slots->GlobalValues; + NumberedMetadata = Slots->MetadataNodes; + for (const auto &I : Slots->NamedTypes) + NamedTypes.insert( + std::make_pair(I.getKey(), std::make_pair(I.second, LocTy()))); + for (const auto &I : Slots->Types) + NumberedTypes.insert( + std::make_pair(I.first, std::make_pair(I.second, LocTy()))); +} + /// ValidateEndOfModule - Do final validity and sanity checks at the end of the /// module. bool LLParser::ValidateEndOfModule() { @@ -181,6 +196,10 @@ bool LLParser::ValidateEndOfModule() { // the mapping from LLParser as it doesn't need it anymore. Slots->GlobalValues = std::move(NumberedVals); Slots->MetadataNodes = std::move(NumberedMetadata); + for (const auto &I : NamedTypes) + Slots->NamedTypes.insert(std::make_pair(I.getKey(), I.second.first)); + for (const auto &I : NumberedTypes) + Slots->Types.insert(std::make_pair(I.first, I.second.first)); return false; } diff --git a/llvm/lib/AsmParser/LLParser.h b/llvm/lib/AsmParser/LLParser.h index dbbb97ab62a..96fb06a1f29 100644 --- a/llvm/lib/AsmParser/LLParser.h +++ b/llvm/lib/AsmParser/LLParser.h @@ -146,7 +146,7 @@ namespace llvm { Slots(Slots), BlockAddressPFS(nullptr) {} bool Run(); - bool parseStandaloneConstantValue(Constant *&C); + bool parseStandaloneConstantValue(Constant *&C, const SlotMapping *Slots); LLVMContext &getContext() { return Context; } @@ -159,6 +159,10 @@ namespace llvm { return Error(Lex.getLoc(), Msg); } + /// Restore the internal name and slot mappings using the mappings that + /// were created at an earlier parsing stage. + void restoreParsingState(const SlotMapping *Slots); + /// 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. diff --git a/llvm/lib/AsmParser/Parser.cpp b/llvm/lib/AsmParser/Parser.cpp index 6135b43f00d..4e55e62ecf5 100644 --- a/llvm/lib/AsmParser/Parser.cpp +++ b/llvm/lib/AsmParser/Parser.cpp @@ -68,13 +68,13 @@ std::unique_ptr<Module> llvm::parseAssemblyString(StringRef AsmString, } Constant *llvm::parseConstantValue(StringRef Asm, SMDiagnostic &Err, - const Module &M) { + const Module &M, const SlotMapping *Slots) { SourceMgr SM; std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(Asm); SM.AddNewSourceBuffer(std::move(Buf), SMLoc()); Constant *C; if (LLParser(Asm, SM, Err, const_cast<Module *>(&M)) - .parseStandaloneConstantValue(C)) + .parseStandaloneConstantValue(C, Slots)) return nullptr; return C; } diff --git a/llvm/unittests/AsmParser/AsmParserTest.cpp b/llvm/unittests/AsmParser/AsmParserTest.cpp index 099f5b5f923..ef16eb1cfb3 100644 --- a/llvm/unittests/AsmParser/AsmParserTest.cpp +++ b/llvm/unittests/AsmParser/AsmParserTest.cpp @@ -112,4 +112,40 @@ TEST(AsmParserTest, TypeAndConstantValueParsing) { EXPECT_EQ(Error.getMessage(), "expected end of string"); } +TEST(AsmParserTest, TypeAndConstantValueWithSlotMappingParsing) { + LLVMContext &Ctx = getGlobalContext(); + SMDiagnostic Error; + StringRef Source = + "%st = type { i32, i32 }\n" + "@v = common global [50 x %st] zeroinitializer, align 16\n" + "%0 = type { i32, i32, i32, i32 }\n" + "@g = common global [50 x %0] zeroinitializer, align 16\n" + "define void @marker4(i64 %d) {\n" + "entry:\n" + " %conv = trunc i64 %d to i32\n" + " store i32 %conv, i32* getelementptr inbounds " + " ([50 x %st], [50 x %st]* @v, i64 0, i64 0, i32 0), align 16\n" + " store i32 %conv, i32* getelementptr inbounds " + " ([50 x %0], [50 x %0]* @g, i64 0, i64 0, i32 0), align 16\n" + " ret void\n" + "}"; + SlotMapping Mapping; + auto Mod = parseAssemblyString(Source, Error, Ctx, &Mapping); + ASSERT_TRUE(Mod != nullptr); + auto &M = *Mod; + + const Value *V; + V = parseConstantValue("i32* getelementptr inbounds ([50 x %st], [50 x %st]* " + "@v, i64 0, i64 0, i32 0)", + Error, M, &Mapping); + ASSERT_TRUE(V); + ASSERT_TRUE(isa<ConstantExpr>(V)); + + V = parseConstantValue("i32* getelementptr inbounds ([50 x %0], [50 x %0]* " + "@g, i64 0, i64 0, i32 0)", + Error, M, &Mapping); + ASSERT_TRUE(V); + ASSERT_TRUE(isa<ConstantExpr>(V)); +} + } // end anonymous namespace |