[PATCH] D127134: [llvm][DeadArgumentElimination] Add DW_CC_nocall to function metadata when all return values are removed

Venkata Ramanaiah Nalamothu via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 6 10:59:28 PDT 2022


RamNalamothu created this revision.
RamNalamothu added reviewers: dblaikie, scott.linder, t-tye, arsenm.
Herald added subscribers: ormris, hiraditya.
Herald added a project: All.
RamNalamothu requested review of this revision.
Herald added subscribers: llvm-commits, wdng.
Herald added a project: LLVM.

Adding the `DW_CC_nocall` calling convention to the function metadata is needed when all the return values of a function are removed and the return type changed to void as this helps in informing debuggers that it is not safe to call these functions or try to interpret the return value.
This translates to setting `DW_AT_calling_convention` with `DW_CC_nocall` for appropriate DWARF DIEs.

The DWARF5 spec (section 3.3.1.1 Calling Convention Information) says:

If the `DW_AT_calling_convention` attribute is not present, or its value is the constant `DW_CC_normal`, then the subroutine may be safely called by obeying the `standard` calling conventions of the target architecture. If the value of the calling convention attribute is the constant `DW_CC_nocall`, the subroutine does not obey standard calling conventions, and it may not be safe for the debugger to call this subroutine.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D127134

Files:
  llvm/include/llvm/IR/DebugInfoMetadata.h
  llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp
  llvm/test/Transforms/DeadArgElim/2010-04-30-DbgInfo.ll


Index: llvm/test/Transforms/DeadArgElim/2010-04-30-DbgInfo.ll
===================================================================
--- llvm/test/Transforms/DeadArgElim/2010-04-30-DbgInfo.ll
+++ llvm/test/Transforms/DeadArgElim/2010-04-30-DbgInfo.ll
@@ -1,23 +1,27 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature
-; RUN: opt -S -passes=deadargelim < %s | FileCheck %s
+; RUN: opt < %s -S -passes=deadargelim > %t
+; RUN: cat %t | FileCheck %s
+; Test whether DW_CC_nocall calling convention is added when return values are removed and return type changed to void.
+; RUN: cat %t | grep "define internal fastcc void \@add_name_internal"
+; RUN: cat %t | grep DW_CC_nocall
 
 @.str = private constant [1 x i8] zeroinitializer, align 1 ; <[1 x i8]*> [#uses=1]
 
-define i8* @vfs_addname(i8* %name, i32 %len, i32 %hash, i32 %flags) nounwind ssp {
+define i8* @vfs_addname(i8* %name, i32 %len, i32 %hash, i32 %flags) nounwind ssp !dbg !1 {
 ;
 entry:
   call void @llvm.dbg.value(metadata i8* %name, metadata !0, metadata !DIExpression()), !dbg !DILocation(scope: !1)
   call void @llvm.dbg.value(metadata i32 %len, metadata !10, metadata !DIExpression()), !dbg !DILocation(scope: !1)
   call void @llvm.dbg.value(metadata i32 %hash, metadata !11, metadata !DIExpression()), !dbg !DILocation(scope: !1)
   call void @llvm.dbg.value(metadata i32 %flags, metadata !12, metadata !DIExpression()), !dbg !DILocation(scope: !1)
-; CHECK:  call fastcc i8* @add_name_internal(i8* %name, i32 %hash) [[NUW:#[0-9]+]], !dbg !{{[0-9]+}}
+; CHECK:  call fastcc void @add_name_internal(i8* %name, i32 %hash) [[NUW:#[0-9]+]], !dbg !{{[0-9]+}}
   %0 = call fastcc i8* @add_name_internal(i8* %name, i32 %len, i32 %hash, i8 zeroext 0, i32 %flags) nounwind, !dbg !13 ; <i8*> [#uses=1]
-  ret i8* %0, !dbg !13
+  ret i8* %name, !dbg !13
 }
 
 declare void @llvm.dbg.declare(metadata, metadata, metadata) nounwind readnone
 
-define internal fastcc i8* @add_name_internal(i8* %name, i32 %len, i32 %hash, i8 zeroext %extra, i32 %flags) noinline nounwind ssp {
+define internal fastcc i8* @add_name_internal(i8* %name, i32 %len, i32 %hash, i8 zeroext %extra, i32 %flags) noinline nounwind ssp !dbg !16 {
 ;
 entry:
   call void @llvm.dbg.value(metadata i8* %name, metadata !15, metadata !DIExpression()), !dbg !DILocation(scope: !16)
Index: llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp
===================================================================
--- llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp
+++ llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp
@@ -23,6 +23,7 @@
 #include "llvm/IR/Attributes.h"
 #include "llvm/IR/BasicBlock.h"
 #include "llvm/IR/Constants.h"
+#include "llvm/IR/DIBuilder.h"
 #include "llvm/IR/DerivedTypes.h"
 #include "llvm/IR/Function.h"
 #include "llvm/IR/IRBuilder.h"
@@ -1083,6 +1084,15 @@
   for (auto MD : MDs)
     NF->addMetadata(MD.first, *MD.second);
 
+  // If all the return values are removed, add DW_CC_nocall to DISubroutineType
+  // so that debuggers will know it is not safe to call this function or try to
+  // interpret the return value.
+  // FIXME: Should we add DW_CC_nocall simply when NFTy != FTy i.e. whenever
+  // an unused return value or an argument is removed?
+  if (!RetTy->isVoidTy() && NRetTy->isVoidTy() && NF->getSubprogram())
+    // Change CallingConvention to DW_CC_nocall
+    NF->getSubprogram()->getType()->setCC(llvm::dwarf::DW_CC_nocall);
+
   // Now that the old function is dead, delete it.
   F->eraseFromParent();
 
Index: llvm/include/llvm/IR/DebugInfoMetadata.h
===================================================================
--- llvm/include/llvm/IR/DebugInfoMetadata.h
+++ llvm/include/llvm/IR/DebugInfoMetadata.h
@@ -1300,6 +1300,7 @@
   TempDISubroutineType clone() const { return cloneImpl(); }
 
   uint8_t getCC() const { return CC; }
+  void setCC(uint8_t NewCC) { CC = NewCC; }
 
   DITypeRefArray getTypeArray() const {
     return cast_or_null<MDTuple>(getRawTypeArray());


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D127134.434536.patch
Type: text/x-patch
Size: 4018 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20220606/7a940d86/attachment.bin>


More information about the llvm-commits mailing list