brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.3 KiB · 12dd225 Raw
225 lines · cpp
1//===- DILineTableFromLocations.cpp - -------------------------------------===//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 9#include "mlir/Dialect/LLVMIR/Transforms/Passes.h"10 11#include "mlir/Dialect/LLVMIR/LLVMDialect.h"12#include "llvm/BinaryFormat/Dwarf.h"13#include "llvm/Support/Path.h"14 15namespace mlir {16namespace LLVM {17#define GEN_PASS_DEF_DISCOPEFORLLVMFUNCOPPASS18#include "mlir/Dialect/LLVMIR/Transforms/Passes.h.inc"19} // namespace LLVM20} // namespace mlir21 22using namespace mlir;23 24/// Attempt to extract a filename for the given loc.25static FileLineColLoc extractFileLoc(Location loc) {26  if (auto fileLoc = dyn_cast<FileLineColLoc>(loc))27    return fileLoc;28  if (auto nameLoc = dyn_cast<NameLoc>(loc))29    return extractFileLoc(nameLoc.getChildLoc());30  if (auto opaqueLoc = dyn_cast<OpaqueLoc>(loc))31    return extractFileLoc(opaqueLoc.getFallbackLocation());32  if (auto fusedLoc = dyn_cast<FusedLoc>(loc)) {33    for (auto loc : fusedLoc.getLocations()) {34      if (auto fileLoc = extractFileLoc(loc))35        return fileLoc;36    }37  }38  if (auto callerLoc = dyn_cast<CallSiteLoc>(loc))39    return extractFileLoc(callerLoc.getCaller());40  return FileLineColLoc();41}42 43/// Creates a DISubprogramAttr with the provided compile unit and attaches it44/// to the function. Does nothing when the function already has an attached45/// subprogram.46static void addScopeToFunction(LLVM::LLVMFuncOp llvmFunc,47                               LLVM::DICompileUnitAttr compileUnitAttr) {48 49  Location loc = llvmFunc.getLoc();50  if (loc->findInstanceOf<FusedLocWith<LLVM::DISubprogramAttr>>())51    return;52 53  MLIRContext *context = llvmFunc->getContext();54 55  // Filename and line associate to the function.56  LLVM::DIFileAttr fileAttr;57  int64_t line = 1;58  if (FileLineColLoc fileLoc = extractFileLoc(loc)) {59    line = fileLoc.getLine();60    StringRef inputFilePath = fileLoc.getFilename().getValue();61    fileAttr =62        LLVM::DIFileAttr::get(context, llvm::sys::path::filename(inputFilePath),63                              llvm::sys::path::parent_path(inputFilePath));64  } else {65    fileAttr = compileUnitAttr66                   ? compileUnitAttr.getFile()67                   : LLVM::DIFileAttr::get(context, "<unknown>", "");68  }69  auto subroutineTypeAttr =70      LLVM::DISubroutineTypeAttr::get(context, llvm::dwarf::DW_CC_normal, {});71 72  // Figure out debug information (`subprogramFlags` and `compileUnitAttr`) to73  // attach to the function definition / declaration. External functions are74  // declarations only and are defined in a different compile unit, so mark75  // them appropriately in `subprogramFlags` and set an empty `compileUnitAttr`.76  DistinctAttr id;77  auto subprogramFlags = LLVM::DISubprogramFlags::Optimized;78  if (!llvmFunc.isExternal()) {79    id = DistinctAttr::create(UnitAttr::get(context));80    subprogramFlags |= LLVM::DISubprogramFlags::Definition;81  } else {82    compileUnitAttr = {};83  }84  auto funcNameAttr = llvmFunc.getNameAttr();85  auto subprogramAttr = LLVM::DISubprogramAttr::get(86      context, id, compileUnitAttr, fileAttr, funcNameAttr, funcNameAttr,87      fileAttr,88      /*line=*/line, /*scopeLine=*/line, subprogramFlags, subroutineTypeAttr,89      /*retainedNodes=*/{}, /*annotations=*/{});90  llvmFunc->setLoc(FusedLoc::get(context, {loc}, subprogramAttr));91}92 93// Get a nested loc for inlined functions.94static Location getNestedLoc(Operation *op, LLVM::DIScopeAttr scopeAttr,95                             Location calleeLoc) {96  auto calleeFileName = extractFileLoc(calleeLoc).getFilename();97  auto *context = op->getContext();98  LLVM::DIFileAttr calleeFileAttr =99      LLVM::DIFileAttr::get(context, llvm::sys::path::filename(calleeFileName),100                            llvm::sys::path::parent_path(calleeFileName));101  auto lexicalBlockFileAttr = LLVM::DILexicalBlockFileAttr::get(102      context, scopeAttr, calleeFileAttr, /*discriminator=*/0);103  Location loc = calleeLoc;104  // Recurse if the callee location is again a call site.105  if (auto callSiteLoc = dyn_cast<CallSiteLoc>(calleeLoc)) {106    auto nestedLoc = callSiteLoc.getCallee();107    loc = getNestedLoc(op, lexicalBlockFileAttr, nestedLoc);108  }109  return FusedLoc::get(context, {loc}, lexicalBlockFileAttr);110}111 112/// Adds DILexicalBlockFileAttr for operations with CallSiteLoc and operations113/// from different files than their containing function.114static void setLexicalBlockFileAttr(Operation *op) {115  Location opLoc = op->getLoc();116 117  if (auto callSiteLoc = dyn_cast<CallSiteLoc>(opLoc)) {118    auto callerLoc = callSiteLoc.getCaller();119    auto calleeLoc = callSiteLoc.getCallee();120    LLVM::DIScopeAttr scopeAttr;121    // We assemble the full inline stack so the parent of this loc must be a122    // function123    auto funcOp = op->getParentOfType<LLVM::LLVMFuncOp>();124    if (auto funcOpLoc = llvm::dyn_cast_if_present<FusedLoc>(funcOp.getLoc())) {125      scopeAttr = cast<LLVM::DISubprogramAttr>(funcOpLoc.getMetadata());126      op->setLoc(127          CallSiteLoc::get(getNestedLoc(op, scopeAttr, calleeLoc), callerLoc));128    }129 130    return;131  }132 133  auto funcOp = op->getParentOfType<LLVM::LLVMFuncOp>();134  if (!funcOp)135    return;136 137  FileLineColLoc opFileLoc = extractFileLoc(opLoc);138  if (!opFileLoc)139    return;140 141  FileLineColLoc funcFileLoc = extractFileLoc(funcOp.getLoc());142  if (!funcFileLoc)143    return;144 145  StringRef opFile = opFileLoc.getFilename().getValue();146  StringRef funcFile = funcFileLoc.getFilename().getValue();147 148  // Handle cross-file operations: add DILexicalBlockFileAttr when the149  // operation's source file differs from its containing function.150  if (opFile != funcFile) {151    auto funcOpLoc = llvm::dyn_cast_if_present<FusedLoc>(funcOp.getLoc());152    if (!funcOpLoc)153      return;154    auto scopeAttr = dyn_cast<LLVM::DISubprogramAttr>(funcOpLoc.getMetadata());155    if (!scopeAttr)156      return;157 158    auto *context = op->getContext();159    LLVM::DIFileAttr opFileAttr =160        LLVM::DIFileAttr::get(context, llvm::sys::path::filename(opFile),161                              llvm::sys::path::parent_path(opFile));162 163    LLVM::DILexicalBlockFileAttr lexicalBlockFileAttr =164        LLVM::DILexicalBlockFileAttr::get(context, scopeAttr, opFileAttr, 0);165 166    Location newLoc = FusedLoc::get(context, {opLoc}, lexicalBlockFileAttr);167    op->setLoc(newLoc);168  }169}170 171namespace {172/// Add a debug info scope to LLVMFuncOp that are missing it.173struct DIScopeForLLVMFuncOpPass174    : public LLVM::impl::DIScopeForLLVMFuncOpPassBase<175          DIScopeForLLVMFuncOpPass> {176  using Base::Base;177 178  void runOnOperation() override {179    ModuleOp module = getOperation();180    Location loc = module.getLoc();181 182    MLIRContext *context = &getContext();183    if (!context->getLoadedDialect<LLVM::LLVMDialect>()) {184      emitError(loc, "LLVM dialect is not loaded.");185      return signalPassFailure();186    }187 188    // Find a DICompileUnitAttr attached to a parent (the module for example),189    // otherwise create a default one.190    LLVM::DICompileUnitAttr compileUnitAttr;191    if (auto fusedCompileUnitAttr =192            module->getLoc()193                ->findInstanceOf<FusedLocWith<LLVM::DICompileUnitAttr>>()) {194      compileUnitAttr = fusedCompileUnitAttr.getMetadata();195    } else {196      LLVM::DIFileAttr fileAttr;197      if (FileLineColLoc fileLoc = extractFileLoc(loc)) {198        StringRef inputFilePath = fileLoc.getFilename().getValue();199        fileAttr = LLVM::DIFileAttr::get(200            context, llvm::sys::path::filename(inputFilePath),201            llvm::sys::path::parent_path(inputFilePath));202      } else {203        fileAttr = LLVM::DIFileAttr::get(context, "<unknown>", "");204      }205 206      compileUnitAttr = LLVM::DICompileUnitAttr::get(207          DistinctAttr::create(UnitAttr::get(context)), llvm::dwarf::DW_LANG_C,208          fileAttr, StringAttr::get(context, "MLIR"),209          /*isOptimized=*/true, emissionKind);210    }211 212    module.walk<WalkOrder::PreOrder>([&](Operation *op) -> void {213      if (auto funcOp = dyn_cast<LLVM::LLVMFuncOp>(op)) {214        // Create subprograms for each function with the same distinct compile215        // unit.216        addScopeToFunction(funcOp, compileUnitAttr);217      } else {218        setLexicalBlockFileAttr(op);219      }220    });221  }222};223 224} // end anonymous namespace225