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 Module; class SMDiagnostic; class LLVMContext; @@ -27,10 +28,10 @@ /// 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. std::unique_ptr parseAssemblyFile(StringRef Filename, SMDiagnostic &Error, LLVMContext &Context); @@ -40,19 +41,19 @@ /// 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. std::unique_ptr parseAssemblyString(StringRef AsmString, SMDiagnostic &Error, LLVMContext &Context); /// 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 Context Context in which to allocate globals info. std::unique_ptr parseAssembly(MemoryBufferRef F, SMDiagnostic &Err, LLVMContext &Context); @@ -61,12 +62,20 @@ /// 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. +/// \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); +/// 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 @@ -140,6 +140,8 @@ BlockAddressPFS(nullptr) {} bool Run(); + Constant *parseStandaloneConstantValue(); + LLVMContext &getContext() { return Context; } private: @@ -340,6 +342,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 @@ -47,6 +47,20 @@ ValidateEndOfModule(); } +Constant *LLParser::parseStandaloneConstantValue() { + Lex.Lex(); + + Type *Ty = nullptr; + Constant *C = nullptr; + if (ParseType(Ty) || ParseConstantValue(Ty, C)) + return nullptr; + if (Lex.getKind() != lltok::Eof) { + Error(Lex.getLoc(), "expected end of string"); + return nullptr; + } + return C; +} + /// ValidateEndOfModule - Do final validity and sanity checks at the end of the /// module. bool LLParser::ValidateEndOfModule() { @@ -4023,6 +4037,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 @@ -62,3 +62,12 @@ MemoryBufferRef F(AsmString, ""); return parseAssembly(F, Err, Context); } + +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()); + return LLParser(Asm, SM, Err, const_cast(&M)) + .parseStandaloneConstantValue(); +} Index: unittests/AsmParser/AsmParserTest.cpp =================================================================== --- unittests/AsmParser/AsmParserTest.cpp +++ unittests/AsmParser/AsmParserTest.cpp @@ -9,9 +9,11 @@ #include "llvm/ADT/StringRef.h" #include "llvm/AsmParser/Parser.h" +#include "llvm/IR/Constants.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/Support/SourceMgr.h" +#include "llvm/Support/raw_ostream.h" #include "gtest/gtest.h" using namespace llvm; @@ -44,4 +46,44 @@ #endif #endif +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