Index: include/llvm/AsmParser/Parser.h =================================================================== --- include/llvm/AsmParser/Parser.h +++ 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); +/// Parses 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: lib/AsmParser/LLParser.h =================================================================== --- lib/AsmParser/LLParser.h +++ 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: lib/AsmParser/LLParser.cpp =================================================================== --- lib/AsmParser/LLParser.cpp +++ 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() { @@ -4056,6 +4067,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: lib/AsmParser/Parser.cpp =================================================================== --- lib/AsmParser/Parser.cpp +++ 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: unittests/AsmParser/AsmParserTest.cpp =================================================================== --- unittests/AsmParser/AsmParserTest.cpp +++ 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,44 @@ EXPECT_EQ(Mapping.MetadataNodes.count(1), 0u); } +TEST(AsmParserTest, TypeAndConstantValueParsing) { + LLVMContext &Ctx = getGlobalContext(); + Module M("test", Ctx); + SMDiagnostic Error; + 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)); + + 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