Skip to content

Support debug info generation for YUL sources #27

@PavelKopyl

Description

@PavelKopyl

We need to emit complete debug information for YUL sources, including the generation of relevant debug records such as #dbg_declare for local variables. Below is a hackery attempt to enable #dbg_declare:

libsolidity/codegen/mlir/YulToMLIR.cpp
@@ -562,6 +562,7 @@ void YulToMLIRPass::operator()(VariableDeclaration const &decl) {
         getLoc(var.debugData),
         /*resTy=*/mlir::LLVM::LLVMPointerType::get(b.getContext()),
         /*eltTy=*/getDefIntTy(), bExt.genI256Const(1), getDefAlign());
+       addr->setAttr("var_name", b.getStringAttr(var.name.str()));
     trackLocalVarAddr(var.name, addr);
     b.create<mlir::LLVM::StoreOp>(loc, rhsExpr, addr, getDefAlign());
   }

--- a/mlir/lib/Dialect/LLVMIR/Transforms/DIScopeForLLVMFuncOp.cpp
+++ b/mlir/lib/Dialect/LLVMIR/Transforms/DIScopeForLLVMFuncOp.cpp
@@ -34,6 +34,46 @@ static FileLineColLoc extractFileLoc(Location loc) {
   return FileLineColLoc();
 }
 
+static uint32_t getLineFromLoc(mlir::Location loc) {
+  uint32_t line = 1;
+  if (auto fileLoc = mlir::dyn_cast<mlir::FileLineColLoc>(loc))
+    line = fileLoc.getLine();
+  return line;
+}
+
+static void handleDeclareOp(mlir::LLVM::AllocaOp declOp,
+                            mlir::LLVM::DIFileAttr fileAttr,
+                            mlir::LLVM::DIScopeAttr scopeAttr) {
+  mlir::StringAttr varName = declOp->getAttrOfType<StringAttr>("var_name");
+  /*
+  if (auto fusedLoc =
+      mlir::dyn_cast_if_present<mlir::FusedLoc>(declOp.getLoc()))
+    varName = mlir::dyn_cast_if_present<mlir::StringAttr>(
+                        fusedLoc.getMetadata());
+  */
+  if (!varName)
+    return;
+
+  mlir::MLIRContext *context = declOp->getContext();
+  mlir::OpBuilder builder(context);
+  builder.setInsertionPointAfter(declOp);
+
+  auto tyAttr =
+      mlir::LLVM::DIBasicTypeAttr::get(context, llvm::dwarf::DW_TAG_base_type,
+                                                mlir::StringAttr::get(context,
+                                                                      "integer"),
+                                      256, llvm::dwarf::DW_ATE_unsigned);
+
+  Location loc = declOp->getLoc();
+  auto localVarAttr = mlir::LLVM::DILocalVariableAttr::get(
+      context, scopeAttr, varName,
+      fileAttr, getLineFromLoc(loc), 0, /* alignInBits*/ 0,
+      tyAttr);
+  declOp->setLoc(builder.getFusedLoc({loc}, localVarAttr));
+  builder.create<mlir::LLVM::DbgDeclareOp>(loc, declOp,  localVarAttr);
+}
+
+
 /// Creates a DISubprogramAttr with the provided compile unit and attaches it
 /// to the function. Does nothing when the function already has an attached
 /// subprogram.
@@ -81,6 +121,10 @@ static void addScopeToFunction(LLVM::LLVMFuncOp llvmFunc,
       /*line=*/line,
       /*scopeline=*/col, subprogramFlags, subroutineTypeAttr);
   llvmFunc->setLoc(FusedLoc::get(context, {loc}, subprogramAttr));
+
+  llvmFunc.walk([&](mlir::LLVM::AllocaOp declOp) {
+      handleDeclareOp(declOp, fileAttr, subprogramAttr);
+  });
 }
 
 namespace {
@@ -117,7 +161,7 @@ struct DIScopeForLLVMFuncOp
       compileUnitAttr = LLVM::DICompileUnitAttr::get(
           DistinctAttr::create(UnitAttr::get(context)), llvm::dwarf::DW_LANG_C,
           fileAttr, StringAttr::get(context, "MLIR"),
-          /*isOptimized=*/true, LLVM::DIEmissionKind::LineTablesOnly);
+          /*isOptimized=*/true, LLVM::DIEmissionKind::Full);
     }
 
     // Create subprograms for each function with the same distinct compile unit.

The full solution can be based on the flang approach:

  • MLIR attributes are generated by reading information from AST
    We may need to introduce additional YUL dialect operations that are not involved in code generation, but exist solely for emitting debug records
  • Adjust debug attributes and generate debug records when converting Standard dialect to LLVM one

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions