diff options
Diffstat (limited to 'lib/OptRemarks/OptRemarksParser.cpp')
-rw-r--r-- | lib/OptRemarks/OptRemarksParser.cpp | 368 |
1 files changed, 0 insertions, 368 deletions
diff --git a/lib/OptRemarks/OptRemarksParser.cpp b/lib/OptRemarks/OptRemarksParser.cpp deleted file mode 100644 index 0478d2bfbfa6..000000000000 --- a/lib/OptRemarks/OptRemarksParser.cpp +++ /dev/null @@ -1,368 +0,0 @@ -//===- OptRemarksParser.cpp -----------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is dual licensed under the MIT and the University of Illinois Open -// Source Licenses. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file provides utility methods used by clients that want to use the -// parser for optimization remarks in LLVM. -// -//===----------------------------------------------------------------------===// - -#include "llvm-c/OptRemarks.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/Support/SourceMgr.h" -#include "llvm/Support/YAMLTraits.h" - -using namespace llvm; - -namespace { -struct RemarkParser { - /// Source manager for better error messages. - SourceMgr SM; - /// Stream for yaml parsing. - yaml::Stream Stream; - /// Storage for the error stream. - std::string ErrorString; - /// The error stream. - raw_string_ostream ErrorStream; - /// Iterator in the YAML stream. - yaml::document_iterator DI; - /// The parsed remark (if any). - Optional<LLVMOptRemarkEntry> LastRemark; - /// Temporary parsing buffer for the arguments. - SmallVector<LLVMOptRemarkArg, 8> TmpArgs; - /// The state used by the parser to parse a remark entry. Invalidated with - /// every call to `parseYAMLElement`. - struct ParseState { - /// Temporary parsing buffer for the arguments. - SmallVectorImpl<LLVMOptRemarkArg> *Args; - StringRef Type; - StringRef Pass; - StringRef Name; - StringRef Function; - /// Optional. - Optional<StringRef> File; - Optional<unsigned> Line; - Optional<unsigned> Column; - Optional<unsigned> Hotness; - - ParseState(SmallVectorImpl<LLVMOptRemarkArg> &Args) : Args(&Args) {} - /// Use Args only as a **temporary** buffer. - ~ParseState() { Args->clear(); } - }; - - ParseState State; - - /// Set to `true` if we had any errors during parsing. - bool HadAnyErrors = false; - - RemarkParser(StringRef Buf) - : SM(), Stream(Buf, SM), ErrorString(), ErrorStream(ErrorString), - DI(Stream.begin()), LastRemark(), TmpArgs(), State(TmpArgs) { - SM.setDiagHandler(RemarkParser::HandleDiagnostic, this); - } - - /// Parse a YAML element. - Error parseYAMLElement(yaml::Document &Remark); - -private: - /// Parse one key to a string. - /// otherwise. - Error parseKey(StringRef &Result, yaml::KeyValueNode &Node); - /// Parse one value to a string. - Error parseValue(StringRef &Result, yaml::KeyValueNode &Node); - /// Parse one value to an unsigned. - Error parseValue(Optional<unsigned> &Result, yaml::KeyValueNode &Node); - /// Parse a debug location. - Error parseDebugLoc(Optional<StringRef> &File, Optional<unsigned> &Line, - Optional<unsigned> &Column, yaml::KeyValueNode &Node); - /// Parse an argument. - Error parseArg(SmallVectorImpl<LLVMOptRemarkArg> &TmpArgs, yaml::Node &Node); - - /// Handle a diagnostic from the YAML stream. Records the error in the - /// RemarkParser class. - static void HandleDiagnostic(const SMDiagnostic &Diag, void *Ctx) { - assert(Ctx && "Expected non-null Ctx in diagnostic handler."); - auto *Parser = static_cast<RemarkParser *>(Ctx); - Diag.print(/*ProgName=*/nullptr, Parser->ErrorStream, /*ShowColors*/ false, - /*ShowKindLabels*/ true); - } -}; - -class ParseError : public ErrorInfo<ParseError> { -public: - static char ID; - - ParseError(StringRef Message, yaml::Node &Node) - : Message(Message), Node(Node) {} - - void log(raw_ostream &OS) const override { OS << Message; } - std::error_code convertToErrorCode() const override { - return inconvertibleErrorCode(); - } - - StringRef getMessage() const { return Message; } - yaml::Node &getNode() const { return Node; } - -private: - StringRef Message; // No need to hold a full copy of the buffer. - yaml::Node &Node; -}; - -char ParseError::ID = 0; - -static LLVMOptRemarkStringRef toOptRemarkStr(StringRef Str) { - return {Str.data(), static_cast<uint32_t>(Str.size())}; -} - -Error RemarkParser::parseKey(StringRef &Result, yaml::KeyValueNode &Node) { - auto *Key = dyn_cast<yaml::ScalarNode>(Node.getKey()); - if (!Key) - return make_error<ParseError>("key is not a string.", Node); - - Result = Key->getRawValue(); - return Error::success(); -} - -Error RemarkParser::parseValue(StringRef &Result, yaml::KeyValueNode &Node) { - auto *Value = dyn_cast<yaml::ScalarNode>(Node.getValue()); - if (!Value) - return make_error<ParseError>("expected a value of scalar type.", Node); - Result = Value->getRawValue(); - - if (Result.front() == '\'') - Result = Result.drop_front(); - - if (Result.back() == '\'') - Result = Result.drop_back(); - - return Error::success(); -} - -Error RemarkParser::parseValue(Optional<unsigned> &Result, - yaml::KeyValueNode &Node) { - SmallVector<char, 4> Tmp; - auto *Value = dyn_cast<yaml::ScalarNode>(Node.getValue()); - if (!Value) - return make_error<ParseError>("expected a value of scalar type.", Node); - unsigned UnsignedValue = 0; - if (Value->getValue(Tmp).getAsInteger(10, UnsignedValue)) - return make_error<ParseError>("expected a value of integer type.", *Value); - Result = UnsignedValue; - return Error::success(); -} - -Error RemarkParser::parseDebugLoc(Optional<StringRef> &File, - Optional<unsigned> &Line, - Optional<unsigned> &Column, - yaml::KeyValueNode &Node) { - auto *DebugLoc = dyn_cast<yaml::MappingNode>(Node.getValue()); - if (!DebugLoc) - return make_error<ParseError>("expected a value of mapping type.", Node); - - for (yaml::KeyValueNode &DLNode : *DebugLoc) { - StringRef KeyName; - if (Error E = parseKey(KeyName, DLNode)) - return E; - if (KeyName == "File") { - File = StringRef(); // Set the optional to contain a default constructed - // value, to be passed to the parsing function. - if (Error E = parseValue(*File, DLNode)) - return E; - } else if (KeyName == "Column") { - if (Error E = parseValue(Column, DLNode)) - return E; - } else if (KeyName == "Line") { - if (Error E = parseValue(Line, DLNode)) - return E; - } else { - return make_error<ParseError>("unknown entry in DebugLoc map.", DLNode); - } - } - - // If any of the debug loc fields is missing, return an error. - if (!File || !Line || !Column) - return make_error<ParseError>("DebugLoc node incomplete.", Node); - - return Error::success(); -} - -Error RemarkParser::parseArg(SmallVectorImpl<LLVMOptRemarkArg> &Args, - yaml::Node &Node) { - auto *ArgMap = dyn_cast<yaml::MappingNode>(&Node); - if (!ArgMap) - return make_error<ParseError>("expected a value of mapping type.", Node); - - StringRef ValueStr; - StringRef KeyStr; - Optional<StringRef> File; - Optional<unsigned> Line; - Optional<unsigned> Column; - - for (yaml::KeyValueNode &ArgEntry : *ArgMap) { - StringRef KeyName; - if (Error E = parseKey(KeyName, ArgEntry)) - return E; - - // Try to parse debug locs. - if (KeyName == "DebugLoc") { - // Can't have multiple DebugLoc entries per argument. - if (File || Line || Column) - return make_error<ParseError>( - "only one DebugLoc entry is allowed per argument.", ArgEntry); - - if (Error E = parseDebugLoc(File, Line, Column, ArgEntry)) - return E; - continue; - } - - // If we already have a string, error out. - if (!ValueStr.empty()) - return make_error<ParseError>( - "only one string entry is allowed per argument.", ArgEntry); - - // Try to parse a string. - if (Error E = parseValue(ValueStr, ArgEntry)) - return E; - - // Keep the key from the string. - KeyStr = KeyName; - } - - if (KeyStr.empty()) - return make_error<ParseError>("argument key is missing.", *ArgMap); - if (ValueStr.empty()) - return make_error<ParseError>("argument value is missing.", *ArgMap); - - Args.push_back(LLVMOptRemarkArg{ - toOptRemarkStr(KeyStr), toOptRemarkStr(ValueStr), - LLVMOptRemarkDebugLoc{toOptRemarkStr(File.getValueOr(StringRef())), - Line.getValueOr(0), Column.getValueOr(0)}}); - - return Error::success(); -} - -Error RemarkParser::parseYAMLElement(yaml::Document &Remark) { - // Parsing a new remark, clear the previous one. - LastRemark = None; - State = ParseState(TmpArgs); - - auto *Root = dyn_cast<yaml::MappingNode>(Remark.getRoot()); - if (!Root) - return make_error<ParseError>("document root is not of mapping type.", - *Remark.getRoot()); - - State.Type = Root->getRawTag(); - - for (yaml::KeyValueNode &RemarkField : *Root) { - StringRef KeyName; - if (Error E = parseKey(KeyName, RemarkField)) - return E; - - if (KeyName == "Pass") { - if (Error E = parseValue(State.Pass, RemarkField)) - return E; - } else if (KeyName == "Name") { - if (Error E = parseValue(State.Name, RemarkField)) - return E; - } else if (KeyName == "Function") { - if (Error E = parseValue(State.Function, RemarkField)) - return E; - } else if (KeyName == "Hotness") { - if (Error E = parseValue(State.Hotness, RemarkField)) - return E; - } else if (KeyName == "DebugLoc") { - if (Error E = - parseDebugLoc(State.File, State.Line, State.Column, RemarkField)) - return E; - } else if (KeyName == "Args") { - auto *Args = dyn_cast<yaml::SequenceNode>(RemarkField.getValue()); - if (!Args) - return make_error<ParseError>("wrong value type for key.", RemarkField); - - for (yaml::Node &Arg : *Args) - if (Error E = parseArg(*State.Args, Arg)) - return E; - } else { - return make_error<ParseError>("unknown key.", RemarkField); - } - } - - // If the YAML parsing failed, don't even continue parsing. We might - // encounter malformed YAML. - if (Stream.failed()) - return make_error<ParseError>("YAML parsing failed.", *Remark.getRoot()); - - // Check if any of the mandatory fields are missing. - if (State.Type.empty() || State.Pass.empty() || State.Name.empty() || - State.Function.empty()) - return make_error<ParseError>("Type, Pass, Name or Function missing.", - *Remark.getRoot()); - - LastRemark = LLVMOptRemarkEntry{ - toOptRemarkStr(State.Type), - toOptRemarkStr(State.Pass), - toOptRemarkStr(State.Name), - toOptRemarkStr(State.Function), - LLVMOptRemarkDebugLoc{toOptRemarkStr(State.File.getValueOr(StringRef())), - State.Line.getValueOr(0), - State.Column.getValueOr(0)}, - State.Hotness.getValueOr(0), - static_cast<uint32_t>(State.Args->size()), - State.Args->data()}; - - return Error::success(); -} -} // namespace - -// Create wrappers for C Binding types (see CBindingWrapping.h). -DEFINE_SIMPLE_CONVERSION_FUNCTIONS(RemarkParser, LLVMOptRemarkParserRef) - -extern "C" LLVMOptRemarkParserRef LLVMOptRemarkParserCreate(const void *Buf, - uint64_t Size) { - return wrap( - new RemarkParser(StringRef(static_cast<const char *>(Buf), Size))); -} - -extern "C" LLVMOptRemarkEntry * -LLVMOptRemarkParserGetNext(LLVMOptRemarkParserRef Parser) { - RemarkParser &TheParser = *unwrap(Parser); - // Check for EOF. - if (TheParser.HadAnyErrors || TheParser.DI == TheParser.Stream.end()) - return nullptr; - - // Try to parse an entry. - if (Error E = TheParser.parseYAMLElement(*TheParser.DI)) { - handleAllErrors(std::move(E), [&](const ParseError &PE) { - TheParser.Stream.printError(&PE.getNode(), - Twine(PE.getMessage()) + Twine('\n')); - TheParser.HadAnyErrors = true; - }); - return nullptr; - } - - // Move on. - ++TheParser.DI; - - // Return the just-parsed remark. - if (Optional<LLVMOptRemarkEntry> &Entry = TheParser.LastRemark) - return &*Entry; - return nullptr; -} - -extern "C" LLVMBool LLVMOptRemarkParserHasError(LLVMOptRemarkParserRef Parser) { - return unwrap(Parser)->HadAnyErrors; -} - -extern "C" const char * -LLVMOptRemarkParserGetErrorMessage(LLVMOptRemarkParserRef Parser) { - return unwrap(Parser)->ErrorStream.str().c_str(); -} - -extern "C" void LLVMOptRemarkParserDispose(LLVMOptRemarkParserRef Parser) { - delete unwrap(Parser); -} |