summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/AsmParser/Parser.h5
-rw-r--r--llvm/include/llvm/AsmParser/SlotMapping.h12
-rw-r--r--llvm/lib/AsmParser/LLParser.cpp21
-rw-r--r--llvm/lib/AsmParser/LLParser.h6
-rw-r--r--llvm/lib/AsmParser/Parser.cpp4
-rw-r--r--llvm/unittests/AsmParser/AsmParserTest.cpp36
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
OpenPOWER on IntegriCloud