brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.4 KiB · 1469071 Raw
183 lines · cpp
1//===----------------------- CodeRegionGenerator.cpp ------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8/// \file9///10/// This file defines classes responsible for generating llvm-mca11/// CodeRegions from various types of input. llvm-mca only analyzes CodeRegions,12/// so the classes here provide the input-to-CodeRegions translation.13//14//===----------------------------------------------------------------------===//15 16#include "CodeRegionGenerator.h"17#include "llvm/ADT/ArrayRef.h"18#include "llvm/ADT/StringRef.h"19#include "llvm/MC/MCParser/MCTargetAsmParser.h"20#include "llvm/MC/MCTargetOptions.h"21#include "llvm/Support/Error.h"22#include "llvm/Support/SMLoc.h"23#include <memory>24 25namespace llvm {26namespace mca {27 28// This virtual dtor serves as the anchor for the CodeRegionGenerator class.29CodeRegionGenerator::~CodeRegionGenerator() = default;30 31Expected<const CodeRegions &> AsmCodeRegionGenerator::parseCodeRegions(32    const std::unique_ptr<MCInstPrinter> &IP, bool SkipFailures) {33  MCTargetOptions Opts;34  Opts.PreserveAsmComments = false;35  CodeRegions &Regions = getRegions();36  MCStreamerWrapper *Str = getMCStreamer();37 38  // Need to initialize an MCTargetStreamer otherwise39  // certain asm directives will cause a segfault.40  // Using nulls() so that anything emitted by the MCTargetStreamer41  // doesn't show up in the llvm-mca output.42  raw_ostream &OSRef = nulls();43  formatted_raw_ostream FOSRef(OSRef);44  TheTarget.createAsmTargetStreamer(*Str, FOSRef, IP.get());45 46  // Create a MCAsmParser and setup the lexer to recognize llvm-mca ASM47  // comments.48  std::unique_ptr<MCAsmParser> Parser(49      createMCAsmParser(Regions.getSourceMgr(), Ctx, *Str, MAI));50  AsmLexer &Lexer = Parser->getLexer();51  MCACommentConsumer *CCP = getCommentConsumer();52  Lexer.setCommentConsumer(CCP);53  // Enable support for MASM literal numbers (example: 05h, 101b).54  Lexer.setLexMasmIntegers(true);55 56  std::unique_ptr<MCTargetAsmParser> TAP(57      TheTarget.createMCAsmParser(STI, *Parser, MCII, Opts));58  if (!TAP)59    return make_error<StringError>(60        "This target does not support assembly parsing.",61        inconvertibleErrorCode());62  Parser->setTargetParser(*TAP);63  // Parser->Run() confusingly returns true on errors, in which case the errors64  // were already shown to the user. SkipFailures implies continuing in the65  // presence of any kind of failure within the parser, in which case failing66  // input lines are not represented, but the rest of the input remains.67  if (Parser->Run(false) && !SkipFailures) {68    const char *Message = "Assembly input parsing had errors, use "69                          "-skip-unsupported-instructions=parse-failure "70                          "to drop failing lines from the input.";71    return make_error<StringError>(Message, inconvertibleErrorCode());72  }73 74  if (CCP->hadErr())75    return make_error<StringError>("There was an error parsing comments.",76                                   inconvertibleErrorCode());77 78  // Set the assembler dialect from the input. llvm-mca will use this as the79  // default dialect when printing reports.80  AssemblerDialect = Parser->getAssemblerDialect();81  return Regions;82}83 84void AnalysisRegionCommentConsumer::HandleComment(SMLoc Loc,85                                                  StringRef CommentText) {86  // Skip empty comments.87  StringRef Comment(CommentText);88  if (Comment.empty())89    return;90 91  // Skip spaces and tabs.92  unsigned Position = Comment.find_first_not_of(" \t");93  if (Position >= Comment.size())94    // We reached the end of the comment. Bail out.95    return;96 97  Comment = Comment.drop_front(Position);98  if (Comment.consume_front("LLVM-MCA-END")) {99    // Skip spaces and tabs.100    Position = Comment.find_first_not_of(" \t");101    if (Position < Comment.size())102      Comment = Comment.drop_front(Position);103    Regions.endRegion(Comment, Loc);104    return;105  }106 107  // Try to parse the LLVM-MCA-BEGIN comment.108  if (!Comment.consume_front("LLVM-MCA-BEGIN"))109    return;110 111  // Skip spaces and tabs.112  Position = Comment.find_first_not_of(" \t");113  if (Position < Comment.size())114    Comment = Comment.drop_front(Position);115  // Use the rest of the string as a descriptor for this code snippet.116  Regions.beginRegion(Comment, Loc);117}118 119void InstrumentRegionCommentConsumer::HandleComment(SMLoc Loc,120                                                    StringRef CommentText) {121  // Skip empty comments.122  StringRef Comment(CommentText);123  if (Comment.empty())124    return;125 126  // Skip spaces and tabs.127  unsigned Position = Comment.find_first_not_of(" \t");128  if (Position >= Comment.size())129    // We reached the end of the comment. Bail out.130    return;131  Comment = Comment.drop_front(Position);132 133  // Bail out if not an MCA style comment134  if (!Comment.consume_front("LLVM-MCA-"))135    return;136 137  // Skip AnalysisRegion comments138  if (Comment.consume_front("BEGIN") || Comment.consume_front("END"))139    return;140 141  if (IM.shouldIgnoreInstruments())142    return;143 144  auto [InstrumentKind, Data] = Comment.split(" ");145 146  // An error if not of the form LLVM-MCA-TARGET-KIND147  if (!IM.supportsInstrumentType(InstrumentKind)) {148    if (InstrumentKind.empty())149      SM.PrintMessage(150          Loc, llvm::SourceMgr::DK_Error,151          "No instrumentation kind was provided in LLVM-MCA comment");152    else153      SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,154                      "Unknown instrumentation type in LLVM-MCA comment: " +155                          InstrumentKind);156    FoundError = true;157    return;158  }159 160  UniqueInstrument I = IM.createInstrument(InstrumentKind, Data);161  if (!I) {162    if (Data.empty())163      SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,164                      "Failed to create " + InstrumentKind +165                          " instrument with no data");166    else167      SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,168                      "Failed to create " + InstrumentKind +169                          " instrument with data: " + Data);170    FoundError = true;171    return;172  }173 174  // End InstrumentType region if one is open175  if (Regions.isRegionActive(InstrumentKind))176    Regions.endRegion(InstrumentKind, Loc);177  // Start new instrumentation region178  Regions.beginRegion(InstrumentKind, Loc, std::move(I));179}180 181} // namespace mca182} // namespace llvm183