Index: llvm/trunk/include/llvm/AsmParser/Parser.h =================================================================== --- llvm/trunk/include/llvm/AsmParser/Parser.h +++ llvm/trunk/include/llvm/AsmParser/Parser.h @@ -18,6 +18,7 @@ namespace llvm { +class Constant; class LLVMContext; class Module; struct SlotMapping; @@ -79,6 +80,14 @@ bool parseAssemblyInto(MemoryBufferRef F, Module &M, SMDiagnostic &Err, SlotMapping *Slots = nullptr); +/// Parse a type and a constant value in the given string. +/// +/// The constant value can be any LLVM constant, including a constant +/// expression. +/// +/// \return null on error. +Constant *parseConstantValue(StringRef Asm, SMDiagnostic &Err, const Module &M); + } // End llvm namespace #endif Index: llvm/trunk/lib/AsmParser/LLParser.h =================================================================== --- llvm/trunk/lib/AsmParser/LLParser.h +++ llvm/trunk/lib/AsmParser/LLParser.h @@ -143,6 +143,8 @@ Slots(Slots), BlockAddressPFS(nullptr) {} bool Run(); + bool parseStandaloneConstantValue(Constant *&C); + LLVMContext &getContext() { return Context; } private: @@ -343,6 +345,7 @@ bool ConvertValIDToValue(Type *Ty, ValID &ID, Value *&V, PerFunctionState *PFS); + bool parseConstantValue(Type *Ty, Constant *&C); bool ParseValue(Type *Ty, Value *&V, PerFunctionState *PFS); bool ParseValue(Type *Ty, Value *&V, PerFunctionState &PFS) { return ParseValue(Ty, V, &PFS); Index: llvm/trunk/lib/AsmParser/LLParser.cpp =================================================================== --- llvm/trunk/lib/AsmParser/LLParser.cpp +++ llvm/trunk/lib/AsmParser/LLParser.cpp @@ -48,6 +48,17 @@ ValidateEndOfModule(); } +bool LLParser::parseStandaloneConstantValue(Constant *&C) { + Lex.Lex(); + + Type *Ty = nullptr; + if (ParseType(Ty) || parseConstantValue(Ty, C)) + return true; + if (Lex.getKind() != lltok::Eof) + return Error(Lex.getLoc(), "expected end of string"); + return false; +} + /// ValidateEndOfModule - Do final validity and sanity checks at the end of the /// module. bool LLParser::ValidateEndOfModule() { @@ -4065,6 +4076,30 @@ llvm_unreachable("Invalid ValID"); } +bool LLParser::parseConstantValue(Type *Ty, Constant *&C) { + C = nullptr; + ValID ID; + auto Loc = Lex.getLoc(); + if (ParseValID(ID, /*PFS=*/nullptr)) + return true; + switch (ID.Kind) { + case ValID::t_APSInt: + case ValID::t_APFloat: + case ValID::t_Constant: + case ValID::t_ConstantStruct: + case ValID::t_PackedConstantStruct: { + Value *V; + if (ConvertValIDToValue(Ty, ID, V, /*PFS=*/nullptr)) + return true; + assert(isa(V) && "Expected a constant value"); + C = cast(V); + return false; + } + default: + return Error(Loc, "expected a constant value"); + } +} + bool LLParser::ParseValue(Type *Ty, Value *&V, PerFunctionState *PFS) { V = nullptr; ValID ID; Index: llvm/trunk/lib/AsmParser/Parser.cpp =================================================================== --- llvm/trunk/lib/AsmParser/Parser.cpp +++ llvm/trunk/lib/AsmParser/Parser.cpp @@ -66,3 +66,15 @@ MemoryBufferRef F(AsmString, ""); return parseAssembly(F, Err, Context, Slots); } + +Constant *llvm::parseConstantValue(StringRef Asm, SMDiagnostic &Err, + const Module &M) { + SourceMgr SM; + std::unique_ptr Buf = MemoryBuffer::getMemBuffer(Asm); + SM.AddNewSourceBuffer(std::move(Buf), SMLoc()); + Constant *C; + if (LLParser(Asm, SM, Err, const_cast(&M)) + .parseStandaloneConstantValue(C)) + return nullptr; + return C; +} Index: llvm/trunk/unittests/AsmParser/AsmParserTest.cpp =================================================================== --- llvm/trunk/unittests/AsmParser/AsmParserTest.cpp +++ llvm/trunk/unittests/AsmParser/AsmParserTest.cpp @@ -10,6 +10,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/AsmParser/Parser.h" #include "llvm/AsmParser/SlotMapping.h" +#include "llvm/IR/Constants.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/Support/SourceMgr.h" @@ -64,4 +65,51 @@ EXPECT_EQ(Mapping.MetadataNodes.count(1), 0u); } +TEST(AsmParserTest, TypeAndConstantValueParsing) { + LLVMContext &Ctx = getGlobalContext(); + SMDiagnostic Error; + StringRef Source = "define void @test() {\n entry:\n ret void\n}"; + auto Mod = parseAssemblyString(Source, Error, Ctx); + ASSERT_TRUE(Mod != nullptr); + auto &M = *Mod; + + const Value *V; + V = parseConstantValue("double 3.5", Error, M); + ASSERT_TRUE(V); + EXPECT_TRUE(V->getType()->isDoubleTy()); + ASSERT_TRUE(isa(V)); + EXPECT_TRUE(cast(V)->isExactlyValue(3.5)); + + V = parseConstantValue("i32 42", Error, M); + ASSERT_TRUE(V); + EXPECT_TRUE(V->getType()->isIntegerTy()); + ASSERT_TRUE(isa(V)); + EXPECT_TRUE(cast(V)->equalsInt(42)); + + V = parseConstantValue("<4 x i32> ", Error, M); + ASSERT_TRUE(V); + EXPECT_TRUE(V->getType()->isVectorTy()); + ASSERT_TRUE(isa(V)); + + V = parseConstantValue("i32 add (i32 1, i32 2)", Error, M); + ASSERT_TRUE(V); + ASSERT_TRUE(isa(V)); + + V = parseConstantValue("i8* blockaddress(@test, %entry)", Error, M); + ASSERT_TRUE(V); + ASSERT_TRUE(isa(V)); + + EXPECT_FALSE(parseConstantValue("duble 3.25", Error, M)); + EXPECT_EQ(Error.getMessage(), "expected type"); + + EXPECT_FALSE(parseConstantValue("i32 3.25", Error, M)); + EXPECT_EQ(Error.getMessage(), "floating point constant invalid for type"); + + EXPECT_FALSE(parseConstantValue("i32* @foo", Error, M)); + EXPECT_EQ(Error.getMessage(), "expected a constant value"); + + EXPECT_FALSE(parseConstantValue("i32 3, ", Error, M)); + EXPECT_EQ(Error.getMessage(), "expected end of string"); +} + } // end anonymous namespace