Path: blob/main/contrib/llvm-project/llvm/tools/llvm-mca/CodeRegionGenerator.cpp
35258 views
//===----------------------- CodeRegionGenerator.cpp ------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7/// \file8///9/// This file defines classes responsible for generating llvm-mca10/// CodeRegions from various types of input. llvm-mca only analyzes CodeRegions,11/// so the classes here provide the input-to-CodeRegions translation.12//13//===----------------------------------------------------------------------===//1415#include "CodeRegionGenerator.h"16#include "llvm/ADT/ArrayRef.h"17#include "llvm/ADT/StringRef.h"18#include "llvm/MC/MCParser/MCTargetAsmParser.h"19#include "llvm/MC/MCTargetOptions.h"20#include "llvm/Support/Error.h"21#include "llvm/Support/SMLoc.h"22#include <memory>2324namespace llvm {25namespace mca {2627// This virtual dtor serves as the anchor for the CodeRegionGenerator class.28CodeRegionGenerator::~CodeRegionGenerator() {}2930Expected<const CodeRegions &> AsmCodeRegionGenerator::parseCodeRegions(31const std::unique_ptr<MCInstPrinter> &IP, bool SkipFailures) {32MCTargetOptions Opts;33Opts.PreserveAsmComments = false;34CodeRegions &Regions = getRegions();35MCStreamerWrapper *Str = getMCStreamer();3637// Need to initialize an MCTargetStreamer otherwise38// certain asm directives will cause a segfault.39// Using nulls() so that anything emitted by the MCTargetStreamer40// doesn't show up in the llvm-mca output.41raw_ostream &OSRef = nulls();42formatted_raw_ostream FOSRef(OSRef);43TheTarget.createAsmTargetStreamer(*Str, FOSRef, IP.get());4445// Create a MCAsmParser and setup the lexer to recognize llvm-mca ASM46// comments.47std::unique_ptr<MCAsmParser> Parser(48createMCAsmParser(Regions.getSourceMgr(), Ctx, *Str, MAI));49MCAsmLexer &Lexer = Parser->getLexer();50MCACommentConsumer *CCP = getCommentConsumer();51Lexer.setCommentConsumer(CCP);52// Enable support for MASM literal numbers (example: 05h, 101b).53Lexer.setLexMasmIntegers(true);5455std::unique_ptr<MCTargetAsmParser> TAP(56TheTarget.createMCAsmParser(STI, *Parser, MCII, Opts));57if (!TAP)58return make_error<StringError>(59"This target does not support assembly parsing.",60inconvertibleErrorCode());61Parser->setTargetParser(*TAP);62// Parser->Run() confusingly returns true on errors, in which case the errors63// were already shown to the user. SkipFailures implies continuing in the64// presence of any kind of failure within the parser, in which case failing65// input lines are not represented, but the rest of the input remains.66if (Parser->Run(false) && !SkipFailures) {67const char *Message = "Assembly input parsing had errors, use "68"-skip-unsupported-instructions=parse-failure "69"to drop failing lines from the input.";70return make_error<StringError>(Message, inconvertibleErrorCode());71}7273if (CCP->hadErr())74return make_error<StringError>("There was an error parsing comments.",75inconvertibleErrorCode());7677// Set the assembler dialect from the input. llvm-mca will use this as the78// default dialect when printing reports.79AssemblerDialect = Parser->getAssemblerDialect();80return Regions;81}8283void AnalysisRegionCommentConsumer::HandleComment(SMLoc Loc,84StringRef CommentText) {85// Skip empty comments.86StringRef Comment(CommentText);87if (Comment.empty())88return;8990// Skip spaces and tabs.91unsigned Position = Comment.find_first_not_of(" \t");92if (Position >= Comment.size())93// We reached the end of the comment. Bail out.94return;9596Comment = Comment.drop_front(Position);97if (Comment.consume_front("LLVM-MCA-END")) {98// Skip spaces and tabs.99Position = Comment.find_first_not_of(" \t");100if (Position < Comment.size())101Comment = Comment.drop_front(Position);102Regions.endRegion(Comment, Loc);103return;104}105106// Try to parse the LLVM-MCA-BEGIN comment.107if (!Comment.consume_front("LLVM-MCA-BEGIN"))108return;109110// Skip spaces and tabs.111Position = Comment.find_first_not_of(" \t");112if (Position < Comment.size())113Comment = Comment.drop_front(Position);114// Use the rest of the string as a descriptor for this code snippet.115Regions.beginRegion(Comment, Loc);116}117118void InstrumentRegionCommentConsumer::HandleComment(SMLoc Loc,119StringRef CommentText) {120// Skip empty comments.121StringRef Comment(CommentText);122if (Comment.empty())123return;124125// Skip spaces and tabs.126unsigned Position = Comment.find_first_not_of(" \t");127if (Position >= Comment.size())128// We reached the end of the comment. Bail out.129return;130Comment = Comment.drop_front(Position);131132// Bail out if not an MCA style comment133if (!Comment.consume_front("LLVM-MCA-"))134return;135136// Skip AnalysisRegion comments137if (Comment.consume_front("BEGIN") || Comment.consume_front("END"))138return;139140if (IM.shouldIgnoreInstruments())141return;142143auto [InstrumentKind, Data] = Comment.split(" ");144145// An error if not of the form LLVM-MCA-TARGET-KIND146if (!IM.supportsInstrumentType(InstrumentKind)) {147if (InstrumentKind.empty())148SM.PrintMessage(149Loc, llvm::SourceMgr::DK_Error,150"No instrumentation kind was provided in LLVM-MCA comment");151else152SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,153"Unknown instrumentation type in LLVM-MCA comment: " +154InstrumentKind);155FoundError = true;156return;157}158159UniqueInstrument I = IM.createInstrument(InstrumentKind, Data);160if (!I) {161if (Data.empty())162SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,163"Failed to create " + InstrumentKind +164" instrument with no data");165else166SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,167"Failed to create " + InstrumentKind +168" instrument with data: " + Data);169FoundError = true;170return;171}172173// End InstrumentType region if one is open174if (Regions.isRegionActive(InstrumentKind))175Regions.endRegion(InstrumentKind, Loc);176// Start new instrumentation region177Regions.beginRegion(InstrumentKind, Loc, std::move(I));178}179180} // namespace mca181} // namespace llvm182183184