1*0b57cec5SDimitry Andric //===----------------------- CodeRegionGenerator.cpp ------------*- C++ -*-===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric /// \file 9*0b57cec5SDimitry Andric /// 10*0b57cec5SDimitry Andric /// This file defines classes responsible for generating llvm-mca 11*0b57cec5SDimitry Andric /// CodeRegions from various types of input. llvm-mca only analyzes CodeRegions, 12*0b57cec5SDimitry Andric /// so the classes here provide the input-to-CodeRegions translation. 13*0b57cec5SDimitry Andric // 14*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 15*0b57cec5SDimitry Andric 16*0b57cec5SDimitry Andric #include "CodeRegionGenerator.h" 17*0b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h" 18*0b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 19*0b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCTargetAsmParser.h" 20*0b57cec5SDimitry Andric #include "llvm/MC/MCStreamer.h" 21*0b57cec5SDimitry Andric #include "llvm/MC/MCTargetOptions.h" 22*0b57cec5SDimitry Andric #include "llvm/Support/Error.h" 23*0b57cec5SDimitry Andric #include "llvm/Support/SMLoc.h" 24*0b57cec5SDimitry Andric #include <memory> 25*0b57cec5SDimitry Andric 26*0b57cec5SDimitry Andric namespace llvm { 27*0b57cec5SDimitry Andric namespace mca { 28*0b57cec5SDimitry Andric 29*0b57cec5SDimitry Andric // This virtual dtor serves as the anchor for the CodeRegionGenerator class. 30*0b57cec5SDimitry Andric CodeRegionGenerator::~CodeRegionGenerator() {} 31*0b57cec5SDimitry Andric 32*0b57cec5SDimitry Andric // A comment consumer that parses strings. The only valid tokens are strings. 33*0b57cec5SDimitry Andric class MCACommentConsumer : public AsmCommentConsumer { 34*0b57cec5SDimitry Andric public: 35*0b57cec5SDimitry Andric CodeRegions &Regions; 36*0b57cec5SDimitry Andric 37*0b57cec5SDimitry Andric MCACommentConsumer(CodeRegions &R) : Regions(R) {} 38*0b57cec5SDimitry Andric void HandleComment(SMLoc Loc, StringRef CommentText) override; 39*0b57cec5SDimitry Andric }; 40*0b57cec5SDimitry Andric 41*0b57cec5SDimitry Andric // This class provides the callbacks that occur when parsing input assembly. 42*0b57cec5SDimitry Andric class MCStreamerWrapper final : public MCStreamer { 43*0b57cec5SDimitry Andric CodeRegions &Regions; 44*0b57cec5SDimitry Andric 45*0b57cec5SDimitry Andric public: 46*0b57cec5SDimitry Andric MCStreamerWrapper(MCContext &Context, mca::CodeRegions &R) 47*0b57cec5SDimitry Andric : MCStreamer(Context), Regions(R) {} 48*0b57cec5SDimitry Andric 49*0b57cec5SDimitry Andric // We only want to intercept the emission of new instructions. 50*0b57cec5SDimitry Andric virtual void EmitInstruction(const MCInst &Inst, 51*0b57cec5SDimitry Andric const MCSubtargetInfo &/* unused */) override { 52*0b57cec5SDimitry Andric Regions.addInstruction(Inst); 53*0b57cec5SDimitry Andric } 54*0b57cec5SDimitry Andric 55*0b57cec5SDimitry Andric bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override { 56*0b57cec5SDimitry Andric return true; 57*0b57cec5SDimitry Andric } 58*0b57cec5SDimitry Andric 59*0b57cec5SDimitry Andric void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, 60*0b57cec5SDimitry Andric unsigned ByteAlignment) override {} 61*0b57cec5SDimitry Andric void EmitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr, 62*0b57cec5SDimitry Andric uint64_t Size = 0, unsigned ByteAlignment = 0, 63*0b57cec5SDimitry Andric SMLoc Loc = SMLoc()) override {} 64*0b57cec5SDimitry Andric void EmitGPRel32Value(const MCExpr *Value) override {} 65*0b57cec5SDimitry Andric void BeginCOFFSymbolDef(const MCSymbol *Symbol) override {} 66*0b57cec5SDimitry Andric void EmitCOFFSymbolStorageClass(int StorageClass) override {} 67*0b57cec5SDimitry Andric void EmitCOFFSymbolType(int Type) override {} 68*0b57cec5SDimitry Andric void EndCOFFSymbolDef() override {} 69*0b57cec5SDimitry Andric 70*0b57cec5SDimitry Andric ArrayRef<MCInst> GetInstructionSequence(unsigned Index) const { 71*0b57cec5SDimitry Andric return Regions.getInstructionSequence(Index); 72*0b57cec5SDimitry Andric } 73*0b57cec5SDimitry Andric }; 74*0b57cec5SDimitry Andric 75*0b57cec5SDimitry Andric void MCACommentConsumer::HandleComment(SMLoc Loc, StringRef CommentText) { 76*0b57cec5SDimitry Andric // Skip empty comments. 77*0b57cec5SDimitry Andric StringRef Comment(CommentText); 78*0b57cec5SDimitry Andric if (Comment.empty()) 79*0b57cec5SDimitry Andric return; 80*0b57cec5SDimitry Andric 81*0b57cec5SDimitry Andric // Skip spaces and tabs. 82*0b57cec5SDimitry Andric unsigned Position = Comment.find_first_not_of(" \t"); 83*0b57cec5SDimitry Andric if (Position >= Comment.size()) 84*0b57cec5SDimitry Andric // We reached the end of the comment. Bail out. 85*0b57cec5SDimitry Andric return; 86*0b57cec5SDimitry Andric 87*0b57cec5SDimitry Andric Comment = Comment.drop_front(Position); 88*0b57cec5SDimitry Andric if (Comment.consume_front("LLVM-MCA-END")) { 89*0b57cec5SDimitry Andric // Skip spaces and tabs. 90*0b57cec5SDimitry Andric Position = Comment.find_first_not_of(" \t"); 91*0b57cec5SDimitry Andric if (Position < Comment.size()) 92*0b57cec5SDimitry Andric Comment = Comment.drop_front(Position); 93*0b57cec5SDimitry Andric Regions.endRegion(Comment, Loc); 94*0b57cec5SDimitry Andric return; 95*0b57cec5SDimitry Andric } 96*0b57cec5SDimitry Andric 97*0b57cec5SDimitry Andric // Try to parse the LLVM-MCA-BEGIN comment. 98*0b57cec5SDimitry Andric if (!Comment.consume_front("LLVM-MCA-BEGIN")) 99*0b57cec5SDimitry Andric return; 100*0b57cec5SDimitry Andric 101*0b57cec5SDimitry Andric // Skip spaces and tabs. 102*0b57cec5SDimitry Andric Position = Comment.find_first_not_of(" \t"); 103*0b57cec5SDimitry Andric if (Position < Comment.size()) 104*0b57cec5SDimitry Andric Comment = Comment.drop_front(Position); 105*0b57cec5SDimitry Andric // Use the rest of the string as a descriptor for this code snippet. 106*0b57cec5SDimitry Andric Regions.beginRegion(Comment, Loc); 107*0b57cec5SDimitry Andric } 108*0b57cec5SDimitry Andric 109*0b57cec5SDimitry Andric Expected<const CodeRegions &> AsmCodeRegionGenerator::parseCodeRegions() { 110*0b57cec5SDimitry Andric MCTargetOptions Opts; 111*0b57cec5SDimitry Andric Opts.PreserveAsmComments = false; 112*0b57cec5SDimitry Andric MCStreamerWrapper Str(Ctx, Regions); 113*0b57cec5SDimitry Andric 114*0b57cec5SDimitry Andric // Create a MCAsmParser and setup the lexer to recognize llvm-mca ASM 115*0b57cec5SDimitry Andric // comments. 116*0b57cec5SDimitry Andric std::unique_ptr<MCAsmParser> Parser( 117*0b57cec5SDimitry Andric createMCAsmParser(Regions.getSourceMgr(), Ctx, Str, MAI)); 118*0b57cec5SDimitry Andric MCAsmLexer &Lexer = Parser->getLexer(); 119*0b57cec5SDimitry Andric MCACommentConsumer CC(Regions); 120*0b57cec5SDimitry Andric Lexer.setCommentConsumer(&CC); 121*0b57cec5SDimitry Andric 122*0b57cec5SDimitry Andric std::unique_ptr<MCTargetAsmParser> TAP( 123*0b57cec5SDimitry Andric TheTarget.createMCAsmParser(STI, *Parser, MCII, Opts)); 124*0b57cec5SDimitry Andric if (!TAP) 125*0b57cec5SDimitry Andric return make_error<StringError>( 126*0b57cec5SDimitry Andric "This target does not support assembly parsing.", 127*0b57cec5SDimitry Andric inconvertibleErrorCode()); 128*0b57cec5SDimitry Andric Parser->setTargetParser(*TAP); 129*0b57cec5SDimitry Andric Parser->Run(false); 130*0b57cec5SDimitry Andric 131*0b57cec5SDimitry Andric // Set the assembler dialect from the input. llvm-mca will use this as the 132*0b57cec5SDimitry Andric // default dialect when printing reports. 133*0b57cec5SDimitry Andric AssemblerDialect = Parser->getAssemblerDialect(); 134*0b57cec5SDimitry Andric return Regions; 135*0b57cec5SDimitry Andric } 136*0b57cec5SDimitry Andric 137*0b57cec5SDimitry Andric } // namespace mca 138*0b57cec5SDimitry Andric } // namespace llvm 139