From: Raphael Isemann Date: Mon, 17 May 2021 12:02:48 +0000 (+0200) Subject: [DebugInfo] Fix DWARF expressions for __block vars that are not on the heap X-Git-Tag: llvmorg-14-init~6423 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=888ce70af288168136cf1ca658c3cf6d6759bb3f;p=platform%2Fupstream%2Fllvm.git [DebugInfo] Fix DWARF expressions for __block vars that are not on the heap `__block` variables used to be always stored on the head instead of stack. D51564 allowed `__block` variables to the stored on the stack like normal variablesif they not captured by any escaping block, but the debug-info generation code wasn't made aware of it so we still unconditionally emit DWARF expressions pointing to the heap. This patch makes CGDebugInfo use the `EscapingByref` introduced in D51564 that tracks whether the `__block` variable is actually on the heap. If it's stored on the stack instead we just use the debug info we would generate for normal variables instead. Reviewed By: ahatanak, aprantl Differential Revision: https://reviews.llvm.org/D99946 --- diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 3d96bf1..fefcf7a 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -4303,7 +4303,9 @@ llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const VarDecl *VD, auto *Scope = cast(LexicalBlockStack.back()); StringRef Name = VD->getName(); if (!Name.empty()) { - if (VD->hasAttr()) { + // __block vars are stored on the heap if they are captured by a block that + // can escape the local scope. + if (VD->isEscapingByref()) { // Here, we need an offset *into* the alloca. CharUnits offset = CharUnits::fromQuantity(32); Expr.push_back(llvm::dwarf::DW_OP_plus_uconst); diff --git a/clang/test/CodeGen/debug-info-block-expr.c b/clang/test/CodeGen/debug-info-block-expr.c index 009e780..5626c5c 100644 --- a/clang/test/CodeGen/debug-info-block-expr.c +++ b/clang/test/CodeGen/debug-info-block-expr.c @@ -1,9 +1,55 @@ // RUN: %clang_cc1 -fblocks -debug-info-kind=limited -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -DDEAD_CODE -fblocks -debug-info-kind=limited -emit-llvm -o - %s | FileCheck %s + +typedef void (^BlockTy)(); +void escapeFunc(BlockTy); +typedef void (^BlockTy)(); +void noEscapeFunc(__attribute__((noescape)) BlockTy); + +// Verify that the desired DIExpression are generated for escaping (i.e, not +// 'noescape') blocks. +void test_escape_func() { +// CHECK-LABEL: void @test_escape_func +// CHECK: call void @llvm.dbg.declare({{.*}}metadata ![[ESCAPE_VAR:[0-9]+]], metadata !DIExpression(DW_OP_plus_uconst, {{[0-9]+}}, DW_OP_deref, DW_OP_plus_uconst, {{[0-9]+}}){{.*}}) + __block int escape_var; +// Blocks in dead code branches still capture __block variables. +#ifdef DEAD_CODE + if (0) +#endif + escapeFunc(^{ (void)escape_var; }); +} + +// Verify that the desired DIExpression are generated for noescape blocks. +void test_noescape_func() { +// CHECK-LABEL: void @test_noescape_func +// CHECK: call void @llvm.dbg.declare({{.*}}metadata ![[NOESCAPE_VAR:[0-9]+]], metadata !DIExpression()) + __block int noescape_var; + noEscapeFunc(^{ (void)noescape_var; }); +} + // Verify that the desired DIExpression are generated for blocks. +void test_local_block() { +// CHECK-LABEL: void @test_local_block +// CHECK: call void @llvm.dbg.declare({{.*}}metadata ![[BLOCK_VAR:[0-9]+]], metadata !DIExpression(DW_OP_plus_uconst, {{[0-9]+}}, DW_OP_deref, DW_OP_plus_uconst, {{[0-9]+}}){{.*}}) + __block int block_var; -void test() { -// CHECK: call void @llvm.dbg.declare({{.*}}!DIExpression(DW_OP_plus_uconst, {{[0-9]+}}, DW_OP_deref, DW_OP_plus_uconst, {{[0-9]+}}){{.*}}) - __block int i; +// CHECK-LABEL: @__test_local_block_block_invoke // CHECK: call void @llvm.dbg.declare({{.*}}!DIExpression(DW_OP_deref, DW_OP_plus_uconst, {{[0-9]+}}, DW_OP_deref, DW_OP_plus_uconst, {{[0-9]+}}, DW_OP_deref, DW_OP_plus_uconst, {{[0-9]+}}){{.*}}) - ^ { i = 1; }(); + ^ { block_var = 1; }(); +} + +// Verify that the desired DIExpression are generated for __block vars not used +// in any block. +void test_unused() { +// CHECK-LABEL: void @test_unused +// CHECK: call void @llvm.dbg.declare({{.*}}metadata ![[UNUSED_VAR:[0-9]+]], metadata !DIExpression()) + __block int unused_var; +// Use i (not inside a block). + ++unused_var; } + +// CHECK: ![[ESCAPE_VAR]] = !DILocalVariable(name: "escape_var" +// CHECK: ![[NOESCAPE_VAR]] = !DILocalVariable(name: "noescape_var" +// CHECK: ![[BLOCK_VAR]] = !DILocalVariable(name: "block_var" +// CHECK: ![[UNUSED_VAR]] = !DILocalVariable(name: "unused_var" +