123f7106eSMatt Davis //===----------------------- CodeRegionGenerator.cpp ------------*- C++ -*-===// 223f7106eSMatt Davis // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 623f7106eSMatt Davis // 723f7106eSMatt Davis //===----------------------------------------------------------------------===// 823f7106eSMatt Davis /// \file 923f7106eSMatt Davis /// 1023f7106eSMatt Davis /// This file defines classes responsible for generating llvm-mca 1123f7106eSMatt Davis /// CodeRegions from various types of input. llvm-mca only analyzes CodeRegions, 1223f7106eSMatt Davis /// so the classes here provide the input-to-CodeRegions translation. 1323f7106eSMatt Davis // 1423f7106eSMatt Davis //===----------------------------------------------------------------------===// 1523f7106eSMatt Davis 1623f7106eSMatt Davis #include "CodeRegionGenerator.h" 1723f7106eSMatt Davis #include "llvm/ADT/ArrayRef.h" 1823f7106eSMatt Davis #include "llvm/ADT/StringRef.h" 1923f7106eSMatt Davis #include "llvm/MC/MCParser/MCTargetAsmParser.h" 2023f7106eSMatt Davis #include "llvm/MC/MCTargetOptions.h" 2123f7106eSMatt Davis #include "llvm/Support/Error.h" 2223f7106eSMatt Davis #include "llvm/Support/SMLoc.h" 2323f7106eSMatt Davis #include <memory> 2423f7106eSMatt Davis 2523f7106eSMatt Davis namespace llvm { 2623f7106eSMatt Davis namespace mca { 2723f7106eSMatt Davis 2823f7106eSMatt Davis // This virtual dtor serves as the anchor for the CodeRegionGenerator class. 2923f7106eSMatt Davis CodeRegionGenerator::~CodeRegionGenerator() {} 3023f7106eSMatt Davis 3198e342dcSMichael Maitland Expected<const CodeRegions &> AsmCodeRegionGenerator::parseCodeRegions( 321de0535eSPeter Waller const std::unique_ptr<MCInstPrinter> &IP, bool SkipFailures) { 3398e342dcSMichael Maitland MCTargetOptions Opts; 3498e342dcSMichael Maitland Opts.PreserveAsmComments = false; 3598e342dcSMichael Maitland CodeRegions &Regions = getRegions(); 36ecf372f9SMichael Maitland MCStreamerWrapper *Str = getMCStreamer(); 3798e342dcSMichael Maitland 3898e342dcSMichael Maitland // Need to initialize an MCTargetStreamer otherwise 3998e342dcSMichael Maitland // certain asm directives will cause a segfault. 4098e342dcSMichael Maitland // Using nulls() so that anything emitted by the MCTargetStreamer 4198e342dcSMichael Maitland // doesn't show up in the llvm-mca output. 4298e342dcSMichael Maitland raw_ostream &OSRef = nulls(); 4398e342dcSMichael Maitland formatted_raw_ostream FOSRef(OSRef); 44*e9c85148SFangrui Song TheTarget.createAsmTargetStreamer(*Str, FOSRef, IP.get()); 4598e342dcSMichael Maitland 4698e342dcSMichael Maitland // Create a MCAsmParser and setup the lexer to recognize llvm-mca ASM 4798e342dcSMichael Maitland // comments. 4898e342dcSMichael Maitland std::unique_ptr<MCAsmParser> Parser( 49ecf372f9SMichael Maitland createMCAsmParser(Regions.getSourceMgr(), Ctx, *Str, MAI)); 5098e342dcSMichael Maitland MCAsmLexer &Lexer = Parser->getLexer(); 5198e342dcSMichael Maitland MCACommentConsumer *CCP = getCommentConsumer(); 5298e342dcSMichael Maitland Lexer.setCommentConsumer(CCP); 5398e342dcSMichael Maitland // Enable support for MASM literal numbers (example: 05h, 101b). 5498e342dcSMichael Maitland Lexer.setLexMasmIntegers(true); 5598e342dcSMichael Maitland 5698e342dcSMichael Maitland std::unique_ptr<MCTargetAsmParser> TAP( 5798e342dcSMichael Maitland TheTarget.createMCAsmParser(STI, *Parser, MCII, Opts)); 5898e342dcSMichael Maitland if (!TAP) 5998e342dcSMichael Maitland return make_error<StringError>( 6098e342dcSMichael Maitland "This target does not support assembly parsing.", 6198e342dcSMichael Maitland inconvertibleErrorCode()); 6298e342dcSMichael Maitland Parser->setTargetParser(*TAP); 631de0535eSPeter Waller // Parser->Run() confusingly returns true on errors, in which case the errors 641de0535eSPeter Waller // were already shown to the user. SkipFailures implies continuing in the 651de0535eSPeter Waller // presence of any kind of failure within the parser, in which case failing 661de0535eSPeter Waller // input lines are not represented, but the rest of the input remains. 671de0535eSPeter Waller if (Parser->Run(false) && !SkipFailures) { 681de0535eSPeter Waller const char *Message = "Assembly input parsing had errors, use " 691de0535eSPeter Waller "-skip-unsupported-instructions=parse-failure " 701de0535eSPeter Waller "to drop failing lines from the input."; 711de0535eSPeter Waller return make_error<StringError>(Message, inconvertibleErrorCode()); 721de0535eSPeter Waller } 7398e342dcSMichael Maitland 7498e342dcSMichael Maitland if (CCP->hadErr()) 7598e342dcSMichael Maitland return make_error<StringError>("There was an error parsing comments.", 7698e342dcSMichael Maitland inconvertibleErrorCode()); 7798e342dcSMichael Maitland 7898e342dcSMichael Maitland // Set the assembler dialect from the input. llvm-mca will use this as the 7998e342dcSMichael Maitland // default dialect when printing reports. 8098e342dcSMichael Maitland AssemblerDialect = Parser->getAssemblerDialect(); 8198e342dcSMichael Maitland return Regions; 8298e342dcSMichael Maitland } 8398e342dcSMichael Maitland 8498e342dcSMichael Maitland void AnalysisRegionCommentConsumer::HandleComment(SMLoc Loc, 8598e342dcSMichael Maitland StringRef CommentText) { 8623f7106eSMatt Davis // Skip empty comments. 8723f7106eSMatt Davis StringRef Comment(CommentText); 8823f7106eSMatt Davis if (Comment.empty()) 8923f7106eSMatt Davis return; 9023f7106eSMatt Davis 9123f7106eSMatt Davis // Skip spaces and tabs. 9223f7106eSMatt Davis unsigned Position = Comment.find_first_not_of(" \t"); 9323f7106eSMatt Davis if (Position >= Comment.size()) 9423f7106eSMatt Davis // We reached the end of the comment. Bail out. 9523f7106eSMatt Davis return; 9623f7106eSMatt Davis 9723f7106eSMatt Davis Comment = Comment.drop_front(Position); 9823f7106eSMatt Davis if (Comment.consume_front("LLVM-MCA-END")) { 994e62554bSAndrea Di Biagio // Skip spaces and tabs. 1004e62554bSAndrea Di Biagio Position = Comment.find_first_not_of(" \t"); 1014e62554bSAndrea Di Biagio if (Position < Comment.size()) 1024e62554bSAndrea Di Biagio Comment = Comment.drop_front(Position); 1034e62554bSAndrea Di Biagio Regions.endRegion(Comment, Loc); 10423f7106eSMatt Davis return; 10523f7106eSMatt Davis } 10623f7106eSMatt Davis 10723f7106eSMatt Davis // Try to parse the LLVM-MCA-BEGIN comment. 10823f7106eSMatt Davis if (!Comment.consume_front("LLVM-MCA-BEGIN")) 10923f7106eSMatt Davis return; 11023f7106eSMatt Davis 11123f7106eSMatt Davis // Skip spaces and tabs. 11223f7106eSMatt Davis Position = Comment.find_first_not_of(" \t"); 11323f7106eSMatt Davis if (Position < Comment.size()) 11423f7106eSMatt Davis Comment = Comment.drop_front(Position); 11523f7106eSMatt Davis // Use the rest of the string as a descriptor for this code snippet. 11623f7106eSMatt Davis Regions.beginRegion(Comment, Loc); 11723f7106eSMatt Davis } 11823f7106eSMatt Davis 11998e342dcSMichael Maitland void InstrumentRegionCommentConsumer::HandleComment(SMLoc Loc, 12098e342dcSMichael Maitland StringRef CommentText) { 12198e342dcSMichael Maitland // Skip empty comments. 12298e342dcSMichael Maitland StringRef Comment(CommentText); 12398e342dcSMichael Maitland if (Comment.empty()) 12498e342dcSMichael Maitland return; 12523f7106eSMatt Davis 12698e342dcSMichael Maitland // Skip spaces and tabs. 12798e342dcSMichael Maitland unsigned Position = Comment.find_first_not_of(" \t"); 12898e342dcSMichael Maitland if (Position >= Comment.size()) 12998e342dcSMichael Maitland // We reached the end of the comment. Bail out. 13098e342dcSMichael Maitland return; 13198e342dcSMichael Maitland Comment = Comment.drop_front(Position); 132e5d59db4SPatrick Holland 13398e342dcSMichael Maitland // Bail out if not an MCA style comment 13498e342dcSMichael Maitland if (!Comment.consume_front("LLVM-MCA-")) 13598e342dcSMichael Maitland return; 13623f7106eSMatt Davis 13798e342dcSMichael Maitland // Skip AnalysisRegion comments 13898e342dcSMichael Maitland if (Comment.consume_front("BEGIN") || Comment.consume_front("END")) 13998e342dcSMichael Maitland return; 14023f7106eSMatt Davis 14198e342dcSMichael Maitland if (IM.shouldIgnoreInstruments()) 14298e342dcSMichael Maitland return; 14398e342dcSMichael Maitland 14498e342dcSMichael Maitland auto [InstrumentKind, Data] = Comment.split(" "); 14598e342dcSMichael Maitland 14698e342dcSMichael Maitland // An error if not of the form LLVM-MCA-TARGET-KIND 14798e342dcSMichael Maitland if (!IM.supportsInstrumentType(InstrumentKind)) { 14898e342dcSMichael Maitland if (InstrumentKind.empty()) 14998e342dcSMichael Maitland SM.PrintMessage( 15098e342dcSMichael Maitland Loc, llvm::SourceMgr::DK_Error, 15198e342dcSMichael Maitland "No instrumentation kind was provided in LLVM-MCA comment"); 15298e342dcSMichael Maitland else 15398e342dcSMichael Maitland SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error, 15498e342dcSMichael Maitland "Unknown instrumentation type in LLVM-MCA comment: " + 15598e342dcSMichael Maitland InstrumentKind); 15698e342dcSMichael Maitland FoundError = true; 15798e342dcSMichael Maitland return; 15898e342dcSMichael Maitland } 15998e342dcSMichael Maitland 16056674e8eSMichael Maitland UniqueInstrument I = IM.createInstrument(InstrumentKind, Data); 16198e342dcSMichael Maitland if (!I) { 16298e342dcSMichael Maitland if (Data.empty()) 16398e342dcSMichael Maitland SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error, 16498e342dcSMichael Maitland "Failed to create " + InstrumentKind + 16598e342dcSMichael Maitland " instrument with no data"); 16698e342dcSMichael Maitland else 16798e342dcSMichael Maitland SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error, 16898e342dcSMichael Maitland "Failed to create " + InstrumentKind + 16998e342dcSMichael Maitland " instrument with data: " + Data); 17098e342dcSMichael Maitland FoundError = true; 17198e342dcSMichael Maitland return; 17298e342dcSMichael Maitland } 17398e342dcSMichael Maitland 17498e342dcSMichael Maitland // End InstrumentType region if one is open 17598e342dcSMichael Maitland if (Regions.isRegionActive(InstrumentKind)) 17698e342dcSMichael Maitland Regions.endRegion(InstrumentKind, Loc); 17798e342dcSMichael Maitland // Start new instrumentation region 17856674e8eSMichael Maitland Regions.beginRegion(InstrumentKind, Loc, std::move(I)); 17923f7106eSMatt Davis } 18023f7106eSMatt Davis 18123f7106eSMatt Davis } // namespace mca 18223f7106eSMatt Davis } // namespace llvm 183