Files
TheRock/compiler/amd-llvm/clang/test/CodeGen/debug-info-block-expr-heterogeneous-dwarf.c
T
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

285 lines
25 KiB
C

// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5
// RUN: %clang_cc1 -fblocks -debug-info-kind=limited -gheterogeneous-dwarf -emit-llvm -disable-llvm-verifier -o - %s | FileCheck %s
// RUN: %clang_cc1 -DDEAD_CODE -fblocks -debug-info-kind=limited -gheterogeneous-dwarf -emit-llvm -disable-llvm-verifier -o - %s | FileCheck --check-prefix=DEADCODE %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.
// CHECK-LABEL: define dso_local void @test_escape_func(
// CHECK-SAME: ) #[[ATTR0:[0-9]+]] !dbg [[DBG4:![0-9]+]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[ESCAPE_VAR:%.*]] = alloca [[STRUCT___BLOCK_BYREF_ESCAPE_VAR:%.*]], align 8
// CHECK-NEXT: [[BLOCK:%.*]] = alloca <{ ptr, i32, i32, ptr, ptr, ptr }>, align 8
// CHECK-NEXT: #dbg_declare(ptr [[ESCAPE_VAR]], [[META9:![0-9]+]], !DIExpression(DIOpArg(0, ptr), DIOpDeref(ptr), DIOpConstant(i64 8), DIOpByteOffset(ptr), DIOpDeref(ptr), DIOpConstant(i64 24), DIOpByteOffset(i32)), [[META11:![0-9]+]])
// CHECK-NEXT: [[BYREF_ISA:%.*]] = getelementptr inbounds nuw [[STRUCT___BLOCK_BYREF_ESCAPE_VAR]], ptr [[ESCAPE_VAR]], i32 0, i32 0, !dbg [[META11]]
// CHECK-NEXT: store ptr null, ptr [[BYREF_ISA]], align 8, !dbg [[META11]]
// CHECK-NEXT: [[BYREF_FORWARDING:%.*]] = getelementptr inbounds nuw [[STRUCT___BLOCK_BYREF_ESCAPE_VAR]], ptr [[ESCAPE_VAR]], i32 0, i32 1, !dbg [[META11]]
// CHECK-NEXT: store ptr [[ESCAPE_VAR]], ptr [[BYREF_FORWARDING]], align 8, !dbg [[META11]]
// CHECK-NEXT: [[BYREF_FLAGS:%.*]] = getelementptr inbounds nuw [[STRUCT___BLOCK_BYREF_ESCAPE_VAR]], ptr [[ESCAPE_VAR]], i32 0, i32 2, !dbg [[META11]]
// CHECK-NEXT: store i32 0, ptr [[BYREF_FLAGS]], align 8, !dbg [[META11]]
// CHECK-NEXT: [[BYREF_SIZE:%.*]] = getelementptr inbounds nuw [[STRUCT___BLOCK_BYREF_ESCAPE_VAR]], ptr [[ESCAPE_VAR]], i32 0, i32 3, !dbg [[META11]]
// CHECK-NEXT: store i32 32, ptr [[BYREF_SIZE]], align 4, !dbg [[META11]]
// CHECK-NEXT: [[ESCAPE_VAR1:%.*]] = getelementptr inbounds nuw [[STRUCT___BLOCK_BYREF_ESCAPE_VAR]], ptr [[ESCAPE_VAR]], i32 0, i32 4, !dbg [[META11]]
// CHECK-NEXT: [[BLOCK_ISA:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr [[BLOCK]], i32 0, i32 0, !dbg [[DBG12:![0-9]+]]
// CHECK-NEXT: store ptr @_NSConcreteStackBlock, ptr [[BLOCK_ISA]], align 8, !dbg [[DBG12]]
// CHECK-NEXT: [[BLOCK_FLAGS:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr [[BLOCK]], i32 0, i32 1, !dbg [[DBG12]]
// CHECK-NEXT: store i32 1107296256, ptr [[BLOCK_FLAGS]], align 8, !dbg [[DBG12]]
// CHECK-NEXT: [[BLOCK_RESERVED:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr [[BLOCK]], i32 0, i32 2, !dbg [[DBG12]]
// CHECK-NEXT: store i32 0, ptr [[BLOCK_RESERVED]], align 4, !dbg [[DBG12]]
// CHECK-NEXT: [[BLOCK_INVOKE:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr [[BLOCK]], i32 0, i32 3, !dbg [[DBG12]]
// CHECK-NEXT: store ptr @__test_escape_func_block_invoke, ptr [[BLOCK_INVOKE]], align 8, !dbg [[DBG12]]
// CHECK-NEXT: [[BLOCK_DESCRIPTOR:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr [[BLOCK]], i32 0, i32 4, !dbg [[DBG12]]
// CHECK-NEXT: store ptr @__block_descriptor_tmp, ptr [[BLOCK_DESCRIPTOR]], align 8, !dbg [[DBG12]]
// CHECK-NEXT: [[BLOCK_CAPTURED:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr [[BLOCK]], i32 0, i32 5, !dbg [[DBG12]]
// CHECK-NEXT: store ptr [[ESCAPE_VAR]], ptr [[BLOCK_CAPTURED]], align 8, !dbg [[DBG12]]
// CHECK-NEXT: call void @escapeFunc(ptr noundef [[BLOCK]]), !dbg [[DBG13:![0-9]+]]
// CHECK-NEXT: call void @_Block_object_dispose(ptr [[ESCAPE_VAR]], i32 8) #[[ATTR3:[0-9]+]], !dbg [[DBG14:![0-9]+]]
// CHECK-NEXT: ret void, !dbg [[DBG14]]
//
// DEADCODE-LABEL: define dso_local void @test_escape_func(
// DEADCODE-SAME: ) #[[ATTR0:[0-9]+]] !dbg [[DBG4:![0-9]+]] {
// DEADCODE-NEXT: [[ENTRY:.*:]]
// DEADCODE-NEXT: [[ESCAPE_VAR:%.*]] = alloca [[STRUCT___BLOCK_BYREF_ESCAPE_VAR:%.*]], align 8
// DEADCODE-NEXT: #dbg_declare(ptr [[ESCAPE_VAR]], [[META9:![0-9]+]], !DIExpression(DIOpArg(0, ptr), DIOpDeref(ptr), DIOpConstant(i64 8), DIOpByteOffset(ptr), DIOpDeref(ptr), DIOpConstant(i64 24), DIOpByteOffset(i32)), [[META11:![0-9]+]])
// DEADCODE-NEXT: [[BYREF_ISA:%.*]] = getelementptr inbounds nuw [[STRUCT___BLOCK_BYREF_ESCAPE_VAR]], ptr [[ESCAPE_VAR]], i32 0, i32 0, !dbg [[META11]]
// DEADCODE-NEXT: store ptr null, ptr [[BYREF_ISA]], align 8, !dbg [[META11]]
// DEADCODE-NEXT: [[BYREF_FORWARDING:%.*]] = getelementptr inbounds nuw [[STRUCT___BLOCK_BYREF_ESCAPE_VAR]], ptr [[ESCAPE_VAR]], i32 0, i32 1, !dbg [[META11]]
// DEADCODE-NEXT: store ptr [[ESCAPE_VAR]], ptr [[BYREF_FORWARDING]], align 8, !dbg [[META11]]
// DEADCODE-NEXT: [[BYREF_FLAGS:%.*]] = getelementptr inbounds nuw [[STRUCT___BLOCK_BYREF_ESCAPE_VAR]], ptr [[ESCAPE_VAR]], i32 0, i32 2, !dbg [[META11]]
// DEADCODE-NEXT: store i32 0, ptr [[BYREF_FLAGS]], align 8, !dbg [[META11]]
// DEADCODE-NEXT: [[BYREF_SIZE:%.*]] = getelementptr inbounds nuw [[STRUCT___BLOCK_BYREF_ESCAPE_VAR]], ptr [[ESCAPE_VAR]], i32 0, i32 3, !dbg [[META11]]
// DEADCODE-NEXT: store i32 32, ptr [[BYREF_SIZE]], align 4, !dbg [[META11]]
// DEADCODE-NEXT: [[ESCAPE_VAR1:%.*]] = getelementptr inbounds nuw [[STRUCT___BLOCK_BYREF_ESCAPE_VAR]], ptr [[ESCAPE_VAR]], i32 0, i32 4, !dbg [[META11]]
// DEADCODE-NEXT: call void @_Block_object_dispose(ptr [[ESCAPE_VAR]], i32 8) #[[ATTR3:[0-9]+]], !dbg [[DBG12:![0-9]+]]
// DEADCODE-NEXT: ret void, !dbg [[DBG12]]
//
void test_escape_func() {
__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.
// CHECK-LABEL: define dso_local void @test_noescape_func(
// CHECK-SAME: ) #[[ATTR0]] !dbg [[DBG33:![0-9]+]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[NOESCAPE_VAR:%.*]] = alloca i32, align 4
// CHECK-NEXT: [[BLOCK:%.*]] = alloca <{ ptr, i32, i32, ptr, ptr, ptr }>, align 8
// CHECK-NEXT: #dbg_declare(ptr [[NOESCAPE_VAR]], [[META35:![0-9]+]], !DIExpression(DIOpArg(0, ptr), DIOpDeref(i32)), [[META36:![0-9]+]])
// CHECK-NEXT: [[BLOCK_ISA:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr [[BLOCK]], i32 0, i32 0, !dbg [[DBG37:![0-9]+]]
// CHECK-NEXT: store ptr @_NSConcreteGlobalBlock, ptr [[BLOCK_ISA]], align 8, !dbg [[DBG37]]
// CHECK-NEXT: [[BLOCK_FLAGS:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr [[BLOCK]], i32 0, i32 1, !dbg [[DBG37]]
// CHECK-NEXT: store i32 1350565888, ptr [[BLOCK_FLAGS]], align 8, !dbg [[DBG37]]
// CHECK-NEXT: [[BLOCK_RESERVED:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr [[BLOCK]], i32 0, i32 2, !dbg [[DBG37]]
// CHECK-NEXT: store i32 0, ptr [[BLOCK_RESERVED]], align 4, !dbg [[DBG37]]
// CHECK-NEXT: [[BLOCK_INVOKE:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr [[BLOCK]], i32 0, i32 3, !dbg [[DBG37]]
// CHECK-NEXT: store ptr @__test_noescape_func_block_invoke, ptr [[BLOCK_INVOKE]], align 8, !dbg [[DBG37]]
// CHECK-NEXT: [[BLOCK_DESCRIPTOR:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr [[BLOCK]], i32 0, i32 4, !dbg [[DBG37]]
// CHECK-NEXT: store ptr @__block_descriptor_tmp.1, ptr [[BLOCK_DESCRIPTOR]], align 8, !dbg [[DBG37]]
// CHECK-NEXT: [[BLOCK_CAPTURED:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr [[BLOCK]], i32 0, i32 5, !dbg [[DBG37]]
// CHECK-NEXT: store ptr [[NOESCAPE_VAR]], ptr [[BLOCK_CAPTURED]], align 8, !dbg [[DBG37]]
// CHECK-NEXT: call void @noEscapeFunc(ptr noundef captures(address) [[BLOCK]]), !dbg [[DBG38:![0-9]+]]
// CHECK-NEXT: ret void, !dbg [[DBG39:![0-9]+]]
//
// DEADCODE-LABEL: define dso_local void @test_noescape_func(
// DEADCODE-SAME: ) #[[ATTR0]] !dbg [[DBG13:![0-9]+]] {
// DEADCODE-NEXT: [[ENTRY:.*:]]
// DEADCODE-NEXT: [[NOESCAPE_VAR:%.*]] = alloca i32, align 4
// DEADCODE-NEXT: [[BLOCK:%.*]] = alloca <{ ptr, i32, i32, ptr, ptr, ptr }>, align 8
// DEADCODE-NEXT: #dbg_declare(ptr [[NOESCAPE_VAR]], [[META15:![0-9]+]], !DIExpression(DIOpArg(0, ptr), DIOpDeref(i32)), [[META16:![0-9]+]])
// DEADCODE-NEXT: [[BLOCK_ISA:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr [[BLOCK]], i32 0, i32 0, !dbg [[DBG17:![0-9]+]]
// DEADCODE-NEXT: store ptr @_NSConcreteGlobalBlock, ptr [[BLOCK_ISA]], align 8, !dbg [[DBG17]]
// DEADCODE-NEXT: [[BLOCK_FLAGS:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr [[BLOCK]], i32 0, i32 1, !dbg [[DBG17]]
// DEADCODE-NEXT: store i32 1350565888, ptr [[BLOCK_FLAGS]], align 8, !dbg [[DBG17]]
// DEADCODE-NEXT: [[BLOCK_RESERVED:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr [[BLOCK]], i32 0, i32 2, !dbg [[DBG17]]
// DEADCODE-NEXT: store i32 0, ptr [[BLOCK_RESERVED]], align 4, !dbg [[DBG17]]
// DEADCODE-NEXT: [[BLOCK_INVOKE:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr [[BLOCK]], i32 0, i32 3, !dbg [[DBG17]]
// DEADCODE-NEXT: store ptr @__test_noescape_func_block_invoke, ptr [[BLOCK_INVOKE]], align 8, !dbg [[DBG17]]
// DEADCODE-NEXT: [[BLOCK_DESCRIPTOR:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr [[BLOCK]], i32 0, i32 4, !dbg [[DBG17]]
// DEADCODE-NEXT: store ptr @__block_descriptor_tmp, ptr [[BLOCK_DESCRIPTOR]], align 8, !dbg [[DBG17]]
// DEADCODE-NEXT: [[BLOCK_CAPTURED:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr [[BLOCK]], i32 0, i32 5, !dbg [[DBG17]]
// DEADCODE-NEXT: store ptr [[NOESCAPE_VAR]], ptr [[BLOCK_CAPTURED]], align 8, !dbg [[DBG17]]
// DEADCODE-NEXT: call void @noEscapeFunc(ptr noundef captures(address) [[BLOCK]]), !dbg [[DBG18:![0-9]+]]
// DEADCODE-NEXT: ret void, !dbg [[DBG19:![0-9]+]]
//
void test_noescape_func() {
__block int noescape_var;
noEscapeFunc(^{ (void)noescape_var; });
}
// Verify that the desired DIExpression are generated for blocks.
// CHECK-LABEL: define dso_local void @test_local_block(
// CHECK-SAME: ) #[[ATTR0]] !dbg [[DBG45:![0-9]+]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[BLOCK_VAR:%.*]] = alloca [[STRUCT___BLOCK_BYREF_BLOCK_VAR:%.*]], align 8
// CHECK-NEXT: [[BLOCK:%.*]] = alloca <{ ptr, i32, i32, ptr, ptr, ptr }>, align 8
// CHECK-NEXT: #dbg_declare(ptr [[BLOCK_VAR]], [[META47:![0-9]+]], !DIExpression(DIOpArg(0, ptr), DIOpDeref(ptr), DIOpConstant(i64 8), DIOpByteOffset(ptr), DIOpDeref(ptr), DIOpConstant(i64 24), DIOpByteOffset(i32)), [[META48:![0-9]+]])
// CHECK-NEXT: [[BYREF_ISA:%.*]] = getelementptr inbounds nuw [[STRUCT___BLOCK_BYREF_BLOCK_VAR]], ptr [[BLOCK_VAR]], i32 0, i32 0, !dbg [[META48]]
// CHECK-NEXT: store ptr null, ptr [[BYREF_ISA]], align 8, !dbg [[META48]]
// CHECK-NEXT: [[BYREF_FORWARDING:%.*]] = getelementptr inbounds nuw [[STRUCT___BLOCK_BYREF_BLOCK_VAR]], ptr [[BLOCK_VAR]], i32 0, i32 1, !dbg [[META48]]
// CHECK-NEXT: store ptr [[BLOCK_VAR]], ptr [[BYREF_FORWARDING]], align 8, !dbg [[META48]]
// CHECK-NEXT: [[BYREF_FLAGS:%.*]] = getelementptr inbounds nuw [[STRUCT___BLOCK_BYREF_BLOCK_VAR]], ptr [[BLOCK_VAR]], i32 0, i32 2, !dbg [[META48]]
// CHECK-NEXT: store i32 0, ptr [[BYREF_FLAGS]], align 8, !dbg [[META48]]
// CHECK-NEXT: [[BYREF_SIZE:%.*]] = getelementptr inbounds nuw [[STRUCT___BLOCK_BYREF_BLOCK_VAR]], ptr [[BLOCK_VAR]], i32 0, i32 3, !dbg [[META48]]
// CHECK-NEXT: store i32 32, ptr [[BYREF_SIZE]], align 4, !dbg [[META48]]
// CHECK-NEXT: [[BLOCK_VAR1:%.*]] = getelementptr inbounds nuw [[STRUCT___BLOCK_BYREF_BLOCK_VAR]], ptr [[BLOCK_VAR]], i32 0, i32 4, !dbg [[META48]]
// CHECK-NEXT: [[BLOCK_ISA:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr [[BLOCK]], i32 0, i32 0, !dbg [[DBG49:![0-9]+]]
// CHECK-NEXT: store ptr @_NSConcreteStackBlock, ptr [[BLOCK_ISA]], align 8, !dbg [[DBG49]]
// CHECK-NEXT: [[BLOCK_FLAGS:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr [[BLOCK]], i32 0, i32 1, !dbg [[DBG49]]
// CHECK-NEXT: store i32 1107296256, ptr [[BLOCK_FLAGS]], align 8, !dbg [[DBG49]]
// CHECK-NEXT: [[BLOCK_RESERVED:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr [[BLOCK]], i32 0, i32 2, !dbg [[DBG49]]
// CHECK-NEXT: store i32 0, ptr [[BLOCK_RESERVED]], align 4, !dbg [[DBG49]]
// CHECK-NEXT: [[BLOCK_INVOKE:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr [[BLOCK]], i32 0, i32 3, !dbg [[DBG49]]
// CHECK-NEXT: store ptr @__test_local_block_block_invoke, ptr [[BLOCK_INVOKE]], align 8, !dbg [[DBG49]]
// CHECK-NEXT: [[BLOCK_DESCRIPTOR:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr [[BLOCK]], i32 0, i32 4, !dbg [[DBG49]]
// CHECK-NEXT: store ptr @__block_descriptor_tmp.2, ptr [[BLOCK_DESCRIPTOR]], align 8, !dbg [[DBG49]]
// CHECK-NEXT: [[BLOCK_CAPTURED:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr [[BLOCK]], i32 0, i32 5, !dbg [[DBG49]]
// CHECK-NEXT: store ptr [[BLOCK_VAR]], ptr [[BLOCK_CAPTURED]], align 8, !dbg [[DBG49]]
// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[STRUCT___BLOCK_LITERAL_GENERIC:%.*]], ptr [[BLOCK]], i32 0, i32 3, !dbg [[DBG49]]
// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8, !dbg [[DBG49]]
// CHECK-NEXT: call void [[TMP1]](ptr noundef [[BLOCK]]), !dbg [[DBG49]]
// CHECK-NEXT: call void @_Block_object_dispose(ptr [[BLOCK_VAR]], i32 8) #[[ATTR3]], !dbg [[DBG50:![0-9]+]]
// CHECK-NEXT: ret void, !dbg [[DBG50]]
//
// DEADCODE-LABEL: define dso_local void @test_local_block(
// DEADCODE-SAME: ) #[[ATTR0]] !dbg [[DBG29:![0-9]+]] {
// DEADCODE-NEXT: [[ENTRY:.*:]]
// DEADCODE-NEXT: [[BLOCK_VAR:%.*]] = alloca [[STRUCT___BLOCK_BYREF_BLOCK_VAR:%.*]], align 8
// DEADCODE-NEXT: [[BLOCK:%.*]] = alloca <{ ptr, i32, i32, ptr, ptr, ptr }>, align 8
// DEADCODE-NEXT: #dbg_declare(ptr [[BLOCK_VAR]], [[META31:![0-9]+]], !DIExpression(DIOpArg(0, ptr), DIOpDeref(ptr), DIOpConstant(i64 8), DIOpByteOffset(ptr), DIOpDeref(ptr), DIOpConstant(i64 24), DIOpByteOffset(i32)), [[META32:![0-9]+]])
// DEADCODE-NEXT: [[BYREF_ISA:%.*]] = getelementptr inbounds nuw [[STRUCT___BLOCK_BYREF_BLOCK_VAR]], ptr [[BLOCK_VAR]], i32 0, i32 0, !dbg [[META32]]
// DEADCODE-NEXT: store ptr null, ptr [[BYREF_ISA]], align 8, !dbg [[META32]]
// DEADCODE-NEXT: [[BYREF_FORWARDING:%.*]] = getelementptr inbounds nuw [[STRUCT___BLOCK_BYREF_BLOCK_VAR]], ptr [[BLOCK_VAR]], i32 0, i32 1, !dbg [[META32]]
// DEADCODE-NEXT: store ptr [[BLOCK_VAR]], ptr [[BYREF_FORWARDING]], align 8, !dbg [[META32]]
// DEADCODE-NEXT: [[BYREF_FLAGS:%.*]] = getelementptr inbounds nuw [[STRUCT___BLOCK_BYREF_BLOCK_VAR]], ptr [[BLOCK_VAR]], i32 0, i32 2, !dbg [[META32]]
// DEADCODE-NEXT: store i32 0, ptr [[BYREF_FLAGS]], align 8, !dbg [[META32]]
// DEADCODE-NEXT: [[BYREF_SIZE:%.*]] = getelementptr inbounds nuw [[STRUCT___BLOCK_BYREF_BLOCK_VAR]], ptr [[BLOCK_VAR]], i32 0, i32 3, !dbg [[META32]]
// DEADCODE-NEXT: store i32 32, ptr [[BYREF_SIZE]], align 4, !dbg [[META32]]
// DEADCODE-NEXT: [[BLOCK_VAR1:%.*]] = getelementptr inbounds nuw [[STRUCT___BLOCK_BYREF_BLOCK_VAR]], ptr [[BLOCK_VAR]], i32 0, i32 4, !dbg [[META32]]
// DEADCODE-NEXT: [[BLOCK_ISA:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr [[BLOCK]], i32 0, i32 0, !dbg [[DBG33:![0-9]+]]
// DEADCODE-NEXT: store ptr @_NSConcreteStackBlock, ptr [[BLOCK_ISA]], align 8, !dbg [[DBG33]]
// DEADCODE-NEXT: [[BLOCK_FLAGS:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr [[BLOCK]], i32 0, i32 1, !dbg [[DBG33]]
// DEADCODE-NEXT: store i32 1107296256, ptr [[BLOCK_FLAGS]], align 8, !dbg [[DBG33]]
// DEADCODE-NEXT: [[BLOCK_RESERVED:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr [[BLOCK]], i32 0, i32 2, !dbg [[DBG33]]
// DEADCODE-NEXT: store i32 0, ptr [[BLOCK_RESERVED]], align 4, !dbg [[DBG33]]
// DEADCODE-NEXT: [[BLOCK_INVOKE:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr [[BLOCK]], i32 0, i32 3, !dbg [[DBG33]]
// DEADCODE-NEXT: store ptr @__test_local_block_block_invoke, ptr [[BLOCK_INVOKE]], align 8, !dbg [[DBG33]]
// DEADCODE-NEXT: [[BLOCK_DESCRIPTOR:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr [[BLOCK]], i32 0, i32 4, !dbg [[DBG33]]
// DEADCODE-NEXT: store ptr @__block_descriptor_tmp.1, ptr [[BLOCK_DESCRIPTOR]], align 8, !dbg [[DBG33]]
// DEADCODE-NEXT: [[BLOCK_CAPTURED:%.*]] = getelementptr inbounds nuw <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr [[BLOCK]], i32 0, i32 5, !dbg [[DBG33]]
// DEADCODE-NEXT: store ptr [[BLOCK_VAR]], ptr [[BLOCK_CAPTURED]], align 8, !dbg [[DBG33]]
// DEADCODE-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[STRUCT___BLOCK_LITERAL_GENERIC:%.*]], ptr [[BLOCK]], i32 0, i32 3, !dbg [[DBG33]]
// DEADCODE-NEXT: [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8, !dbg [[DBG33]]
// DEADCODE-NEXT: call void [[TMP1]](ptr noundef [[BLOCK]]), !dbg [[DBG33]]
// DEADCODE-NEXT: call void @_Block_object_dispose(ptr [[BLOCK_VAR]], i32 8) #[[ATTR3]], !dbg [[DBG34:![0-9]+]]
// DEADCODE-NEXT: ret void, !dbg [[DBG34]]
//
void test_local_block() {
__block int block_var;
// FIXME(KZHURAVL): Update EmitDeclareOfBlockDeclRefVariable and EmitDeclareOfBlockLiteralArgVariable.
^ { block_var = 1; }();
}
// Verify that the desired DIExpression are generated for __block vars not used
// in any block.
// CHECK-LABEL: define dso_local void @test_unused(
// CHECK-SAME: ) #[[ATTR0]] !dbg [[DBG56:![0-9]+]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[UNUSED_VAR:%.*]] = alloca i32, align 4
// CHECK-NEXT: #dbg_declare(ptr [[UNUSED_VAR]], [[META58:![0-9]+]], !DIExpression(DIOpArg(0, ptr), DIOpDeref(i32)), [[META59:![0-9]+]])
// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[UNUSED_VAR]], align 4, !dbg [[DBG60:![0-9]+]]
// CHECK-NEXT: [[INC:%.*]] = add nsw i32 [[TMP0]], 1, !dbg [[DBG60]]
// CHECK-NEXT: store i32 [[INC]], ptr [[UNUSED_VAR]], align 4, !dbg [[DBG60]]
// CHECK-NEXT: ret void, !dbg [[DBG61:![0-9]+]]
//
// DEADCODE-LABEL: define dso_local void @test_unused(
// DEADCODE-SAME: ) #[[ATTR0]] !dbg [[DBG50:![0-9]+]] {
// DEADCODE-NEXT: [[ENTRY:.*:]]
// DEADCODE-NEXT: [[UNUSED_VAR:%.*]] = alloca i32, align 4
// DEADCODE-NEXT: #dbg_declare(ptr [[UNUSED_VAR]], [[META52:![0-9]+]], !DIExpression(DIOpArg(0, ptr), DIOpDeref(i32)), [[META53:![0-9]+]])
// DEADCODE-NEXT: [[TMP0:%.*]] = load i32, ptr [[UNUSED_VAR]], align 4, !dbg [[DBG54:![0-9]+]]
// DEADCODE-NEXT: [[INC:%.*]] = add nsw i32 [[TMP0]], 1, !dbg [[DBG54]]
// DEADCODE-NEXT: store i32 [[INC]], ptr [[UNUSED_VAR]], align 4, !dbg [[DBG54]]
// DEADCODE-NEXT: ret void, !dbg [[DBG55:![0-9]+]]
//
void test_unused() {
__block int unused_var;
// Use i (not inside a block).
++unused_var;
}
//.
// CHECK: [[META0:![0-9]+]] = distinct !DICompileUnit(language: DW_LANG_C11, file: [[META1:![0-9]+]], producer: "{{.*}}clang version {{.*}}", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
// CHECK: [[META1]] = !DIFile(filename: "{{.*}}<stdin>", directory: {{.*}})
// CHECK: [[DBG4]] = distinct !DISubprogram(name: "test_escape_func", scope: [[META5:![0-9]+]], file: [[META5]], line: 60, type: [[META6:![0-9]+]], scopeLine: 60, spFlags: DISPFlagDefinition, unit: [[META0]], retainedNodes: [[META8:![0-9]+]])
// CHECK: [[META5]] = !DIFile(filename: "{{.*}}debug-info-block-expr-heterogeneous-dwarf.c", directory: {{.*}})
// CHECK: [[META6]] = !DISubroutineType(types: [[META7:![0-9]+]])
// CHECK: [[META7]] = !{null}
// CHECK: [[META8]] = !{[[META9]]}
// CHECK: [[META9]] = !DILocalVariable(name: "escape_var", scope: [[DBG4]], file: [[META5]], line: 61, type: [[META10:![0-9]+]])
// CHECK: [[META10]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
// CHECK: [[META11]] = !DILocation(line: 61, column: 15, scope: [[DBG4]])
// CHECK: [[DBG12]] = !DILocation(line: 66, column: 14, scope: [[DBG4]])
// CHECK: [[DBG13]] = !DILocation(line: 66, column: 3, scope: [[DBG4]])
// CHECK: [[DBG14]] = !DILocation(line: 67, column: 1, scope: [[DBG4]])
// CHECK: [[DBG33]] = distinct !DISubprogram(name: "test_noescape_func", scope: [[META5]], file: [[META5]], line: 112, type: [[META6]], scopeLine: 112, spFlags: DISPFlagDefinition, unit: [[META0]], retainedNodes: [[META34:![0-9]+]])
// CHECK: [[META34]] = !{[[META35]]}
// CHECK: [[META35]] = !DILocalVariable(name: "noescape_var", scope: [[DBG33]], file: [[META5]], line: 113, type: [[META10]])
// CHECK: [[META36]] = !DILocation(line: 113, column: 15, scope: [[DBG33]])
// CHECK: [[DBG37]] = !DILocation(line: 114, column: 16, scope: [[DBG33]])
// CHECK: [[DBG38]] = !DILocation(line: 114, column: 3, scope: [[DBG33]])
// CHECK: [[DBG39]] = !DILocation(line: 115, column: 1, scope: [[DBG33]])
// CHECK: [[DBG45]] = distinct !DISubprogram(name: "test_local_block", scope: [[META5]], file: [[META5]], line: 184, type: [[META6]], scopeLine: 184, spFlags: DISPFlagDefinition, unit: [[META0]], retainedNodes: [[META46:![0-9]+]])
// CHECK: [[META46]] = !{[[META47]]}
// CHECK: [[META47]] = !DILocalVariable(name: "block_var", scope: [[DBG45]], file: [[META5]], line: 185, type: [[META10]])
// CHECK: [[META48]] = !DILocation(line: 185, column: 15, scope: [[DBG45]])
// CHECK: [[DBG49]] = !DILocation(line: 188, column: 3, scope: [[DBG45]])
// CHECK: [[DBG50]] = !DILocation(line: 189, column: 1, scope: [[DBG45]])
// CHECK: [[DBG56]] = distinct !DISubprogram(name: "test_unused", scope: [[META5]], file: [[META5]], line: 213, type: [[META6]], scopeLine: 213, spFlags: DISPFlagDefinition, unit: [[META0]], retainedNodes: [[META57:![0-9]+]])
// CHECK: [[META57]] = !{[[META58]]}
// CHECK: [[META58]] = !DILocalVariable(name: "unused_var", scope: [[DBG56]], file: [[META5]], line: 214, type: [[META10]])
// CHECK: [[META59]] = !DILocation(line: 214, column: 15, scope: [[DBG56]])
// CHECK: [[DBG60]] = !DILocation(line: 216, column: 3, scope: [[DBG56]])
// CHECK: [[DBG61]] = !DILocation(line: 217, column: 1, scope: [[DBG56]])
//.
// DEADCODE: [[META0:![0-9]+]] = distinct !DICompileUnit(language: DW_LANG_C11, file: [[META1:![0-9]+]], producer: "{{.*}}clang version {{.*}}", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
// DEADCODE: [[META1]] = !DIFile(filename: "{{.*}}<stdin>", directory: {{.*}})
// DEADCODE: [[DBG4]] = distinct !DISubprogram(name: "test_escape_func", scope: [[META5:![0-9]+]], file: [[META5]], line: 60, type: [[META6:![0-9]+]], scopeLine: 60, spFlags: DISPFlagDefinition, unit: [[META0]], retainedNodes: [[META8:![0-9]+]])
// DEADCODE: [[META5]] = !DIFile(filename: "{{.*}}debug-info-block-expr-heterogeneous-dwarf.c", directory: {{.*}})
// DEADCODE: [[META6]] = !DISubroutineType(types: [[META7:![0-9]+]])
// DEADCODE: [[META7]] = !{null}
// DEADCODE: [[META8]] = !{[[META9]]}
// DEADCODE: [[META9]] = !DILocalVariable(name: "escape_var", scope: [[DBG4]], file: [[META5]], line: 61, type: [[META10:![0-9]+]])
// DEADCODE: [[META10]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
// DEADCODE: [[META11]] = !DILocation(line: 61, column: 15, scope: [[DBG4]])
// DEADCODE: [[DBG12]] = !DILocation(line: 67, column: 1, scope: [[DBG4]])
// DEADCODE: [[DBG13]] = distinct !DISubprogram(name: "test_noescape_func", scope: [[META5]], file: [[META5]], line: 112, type: [[META6]], scopeLine: 112, spFlags: DISPFlagDefinition, unit: [[META0]], retainedNodes: [[META14:![0-9]+]])
// DEADCODE: [[META14]] = !{[[META15]]}
// DEADCODE: [[META15]] = !DILocalVariable(name: "noescape_var", scope: [[DBG13]], file: [[META5]], line: 113, type: [[META10]])
// DEADCODE: [[META16]] = !DILocation(line: 113, column: 15, scope: [[DBG13]])
// DEADCODE: [[DBG17]] = !DILocation(line: 114, column: 16, scope: [[DBG13]])
// DEADCODE: [[DBG18]] = !DILocation(line: 114, column: 3, scope: [[DBG13]])
// DEADCODE: [[DBG19]] = !DILocation(line: 115, column: 1, scope: [[DBG13]])
// DEADCODE: [[DBG29]] = distinct !DISubprogram(name: "test_local_block", scope: [[META5]], file: [[META5]], line: 184, type: [[META6]], scopeLine: 184, spFlags: DISPFlagDefinition, unit: [[META0]], retainedNodes: [[META30:![0-9]+]])
// DEADCODE: [[META30]] = !{[[META31]]}
// DEADCODE: [[META31]] = !DILocalVariable(name: "block_var", scope: [[DBG29]], file: [[META5]], line: 185, type: [[META10]])
// DEADCODE: [[META32]] = !DILocation(line: 185, column: 15, scope: [[DBG29]])
// DEADCODE: [[DBG33]] = !DILocation(line: 188, column: 3, scope: [[DBG29]])
// DEADCODE: [[DBG34]] = !DILocation(line: 189, column: 1, scope: [[DBG29]])
// DEADCODE: [[DBG50]] = distinct !DISubprogram(name: "test_unused", scope: [[META5]], file: [[META5]], line: 213, type: [[META6]], scopeLine: 213, spFlags: DISPFlagDefinition, unit: [[META0]], retainedNodes: [[META51:![0-9]+]])
// DEADCODE: [[META51]] = !{[[META52]]}
// DEADCODE: [[META52]] = !DILocalVariable(name: "unused_var", scope: [[DBG50]], file: [[META5]], line: 214, type: [[META10]])
// DEADCODE: [[META53]] = !DILocation(line: 214, column: 15, scope: [[DBG50]])
// DEADCODE: [[DBG54]] = !DILocation(line: 216, column: 3, scope: [[DBG50]])
// DEADCODE: [[DBG55]] = !DILocation(line: 217, column: 1, scope: [[DBG50]])
//.