https://github.com/yonghong-song updated https://github.com/llvm/llvm-project/pull/237589
>From 6d00a05dd97322b1c4757eb7fa1825b4691d2231 Mon Sep 17 00:00:00 2001 From: Yonghong Song <[email protected]> Date: Tue, 27 Oct 2026 07:58:09 -0700 Subject: [PATCH] [Clang][BPF] Preserve every subscript of multi-dimensional array members A member access is relocated with CO-RE either inside __builtin_preserve_access_index() or through the preserve_access_index attribute on the record. For an array member with more than one subscript, the builtin works, but the attribute does not. With #define __pai __attribute__((preserve_access_index)) struct S { long x; int y; } __pai; union V { long l; struct S m[2][3]; } __pai; struct T { struct S a[2][3]; union V g[3][2]; struct S (*q)[3]; struct S *p[3]; struct S v[2][3][4]; } __pai; the relocations for t->a[1][2].y are: - __builtin_preserve_access_index(t->a[1][2].y): one relocation, struct T::a[1][2].y. - t->a[1][2].y with only the attribute: struct T::a[1] and struct S::y. The offset of [2] is fixed at 32 bytes at compile time, which is wrong if the size of struct S changes. This patch closes this gap. With only the attribute: - emitArraySubscriptGEP() emits a constant subscript as llvm.preserve.array.access.index, instead of a plain GEP, only if IsPreserveAIArrayBase() finds that the base of the subscript comes from a record with the attribute. - IsPreserveAIArrayBase() stripped implicit casts from the base and accepted only a member of such a record, e.g., t->a in t->a[1], or a pointer to such a record. - In t->a[1][2], the base of [2] is the subscript t->a[1], so [2] became a plain GEP. - The BPF backend follows only GEPs with all-zero indices, so that GEP ended the CO-RE access chain. The rest of the access started a new chain, and the offset of [2] was not relocated. - Parentheses had the same effect, e.g., in (t->a)[2], stripping stopped at the ParenExpr. Now IsPreserveAIArrayBase(): - For the second and later subscripts, the base is another ArraySubscriptExpr, e.g., t->a[1] for [2] in t->a[1][2]. It replaces the ArraySubscriptExpr with its base, repeatedly, until the base is no longer a subscript, e.g., the MemberExpr t->a for [2], and checks that as before. - Uses IgnoreParenImpCasts() instead of IgnoreImpCasts(), so a ParenExpr is skipped like an ImplicitCastExpr. - Still stops at an explicit cast or any other operator. The relocations with only the attribute are: - t->a[1][2].y before: struct T::a[1], struct S::y, [2] fixed at 32 bytes after: struct T::a[1][2].y - t->g[2][1].m[1][2].y, struct -> 2-D array -> union -> 2-D array -> struct before: struct T::g[2], union V::m[1], struct S::y, g's [1] and m's [2] fixed after: struct T::g[2][1].m[1][2].y - t->q[1][2].y, a pointer to an array before: struct T::q, struct S::[3], struct S::y, [2] fixed at 32 bytes after: struct T::q, struct S::[5].y - t->p[1][2].y, an array of pointers before: struct T::p[1], struct S::y, [2] fixed at 32 bytes after: struct T::p[1], struct S::[2].y - (t->a[1])[2].y before: struct T::a[1], struct S::y, [2] fixed at 32 bytes after: struct T::a[1][2].y, the same as without parentheses - t->v[n][2][3].y, a 3-D array with a variable n before: struct T::v, struct S::y, [2][3] fixed at 176 bytes after: struct T::v, struct S::[11].y [n] is not relocated in either case, since a variable subscript cannot be preserved, but [2] and [3] after it now are, folded into one index, 2 * 4 + 3 = 11. In each case, "after" is the same as with __builtin_preserve_access_index(). A pointer load still ends the chain, as in the t->q and t->p examples, but the access after the load is now relocated as a whole. --- clang/lib/CodeGen/CGExpr.cpp | 6 +- .../bpf-attr-preserve-access-index-9.c | 195 ++++++++ .../BPF/CORE/offset-reloc-subarray-record.ll | 469 ++++++++++++++++++ 3 files changed, 669 insertions(+), 1 deletion(-) create mode 100644 clang/test/CodeGen/bpf-attr-preserve-access-index-9.c create mode 100644 llvm/test/CodeGen/BPF/CORE/offset-reloc-subarray-record.ll diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 98133ecf1b48fc..ae5f4e723f5129 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -4902,7 +4902,11 @@ static bool IsPreserveAIArrayBase(CodeGenFunction &CGF, const Expr *ArrayBase) { // p[1].a // p[1] will generate a DeclRefExpr and p[1].a is a MemberExpr. // p->b[5] is a MemberExpr example. - const Expr *E = ArrayBase->IgnoreImpCasts(); + const Expr *E = ArrayBase->IgnoreParenImpCasts(); + // In p->b[1][2], the base of [2] is the subscript p->b[1]. Step through + // subscripts to the member p->b. + while (const auto *ASE = dyn_cast<ArraySubscriptExpr>(E)) + E = ASE->getBase()->IgnoreParenImpCasts(); if (const auto *ME = dyn_cast<MemberExpr>(E)) return ME->getMemberDecl()->hasAttr<BPFPreserveAccessIndexAttr>(); diff --git a/clang/test/CodeGen/bpf-attr-preserve-access-index-9.c b/clang/test/CodeGen/bpf-attr-preserve-access-index-9.c new file mode 100644 index 00000000000000..dd9b1ea7911022 --- /dev/null +++ b/clang/test/CodeGen/bpf-attr-preserve-access-index-9.c @@ -0,0 +1,195 @@ +// REQUIRES: bpf-registered-target +// RUN: %clang_cc1 -triple bpf -emit-llvm -debug-info-kind=limited -disable-llvm-passes %s -o - | FileCheck %s + +#define __reloc__ __attribute__((preserve_access_index)) + +// Every subscript of a multi-dimensional array member is preserved, so the +// record behind the array stays in the same access chain. +struct s1 { + long a; + int b; +} __reloc__; +typedef const struct s1 __s1; +typedef struct s1 arr2_t[2][3]; +typedef struct s1 row_t[3]; + +union u1 { + int c; + __s1 d; +} __reloc__; + +struct s2 { + int e; + struct s1 f[2][3]; + volatile union u1 g[2][3]; + struct s1 (*h)[3]; + struct s1 *i[3]; + const arr2_t j; + row_t k[2]; + struct s1 l[2][3][4]; +} __reloc__; +typedef struct s2 __s2; + +union u2 { + int l; + __s1 m[2][3]; +} __reloc__; +typedef union u2 u2row_t[2]; + +struct s3 { + int n; + const u2row_t o[3]; +} __reloc__; + +int test1(__s2 *arg) { return arg->f[1][2].b; } + +// CHECK-LABEL: @test1 +// CHECK-NOT: getelementptr +// CHECK: call ptr @llvm.preserve.struct.access.index.p0.p0(ptr elementtype(%struct.s2) %{{[0-9a-z]+}}, i32 1, i32 1) +// CHECK-NOT: getelementptr +// CHECK: call ptr @llvm.preserve.array.access.index.p0.p0(ptr elementtype([2 x [3 x %struct.s1]]) %{{[0-9a-z]+}}, i32 1, i32 1) +// CHECK-NOT: getelementptr +// CHECK: call ptr @llvm.preserve.array.access.index.p0.p0(ptr elementtype([3 x %struct.s1]) %{{[0-9a-z]+}}, i32 1, i32 2) +// CHECK-NOT: getelementptr +// CHECK: call ptr @llvm.preserve.struct.access.index.p0.p0(ptr elementtype(%struct.s1) %{{[0-9a-z]+}}, i32 1, i32 1) + +int test2(__s2 *arg) { return arg->g[1][2].d.b; } + +// CHECK-LABEL: @test2 +// CHECK-NOT: getelementptr +// CHECK: call ptr @llvm.preserve.struct.access.index.p0.p0(ptr elementtype(%struct.s2) %{{[0-9a-z]+}}, i32 2, i32 2) +// CHECK-NOT: getelementptr +// CHECK: call ptr @llvm.preserve.array.access.index.p0.p0(ptr elementtype([2 x [3 x %union.u1]]) %{{[0-9a-z]+}}, i32 1, i32 1) +// CHECK-NOT: getelementptr +// CHECK: call ptr @llvm.preserve.array.access.index.p0.p0(ptr elementtype([3 x %union.u1]) %{{[0-9a-z]+}}, i32 1, i32 2) +// CHECK-NOT: getelementptr +// CHECK: call ptr @llvm.preserve.union.access.index.p0.p0(ptr %{{[0-9a-z]+}}, i32 1) +// CHECK-NOT: getelementptr +// CHECK: call ptr @llvm.preserve.struct.access.index.p0.p0(ptr elementtype(%struct.s1) %{{[0-9a-z]+}}, i32 1, i32 1) + +int test3(union u2 *arg) { return arg->m[1][2].b; } + +// CHECK-LABEL: @test3 +// CHECK-NOT: getelementptr +// CHECK: call ptr @llvm.preserve.union.access.index.p0.p0(ptr %{{[0-9a-z]+}}, i32 1) +// CHECK-NOT: getelementptr +// CHECK: call ptr @llvm.preserve.array.access.index.p0.p0(ptr elementtype([2 x [3 x %struct.s1]]) %{{[0-9a-z]+}}, i32 1, i32 1) +// CHECK-NOT: getelementptr +// CHECK: call ptr @llvm.preserve.array.access.index.p0.p0(ptr elementtype([3 x %struct.s1]) %{{[0-9a-z]+}}, i32 1, i32 2) +// CHECK-NOT: getelementptr +// CHECK: call ptr @llvm.preserve.struct.access.index.p0.p0(ptr elementtype(%struct.s1) %{{[0-9a-z]+}}, i32 1, i32 1) + +int test4(__s2 *arg) { return arg->h[1][2].b; } + +// CHECK-LABEL: @test4 +// CHECK-NOT: getelementptr +// CHECK: call ptr @llvm.preserve.struct.access.index.p0.p0(ptr elementtype(%struct.s2) %{{[0-9a-z]+}}, i32 3, i32 3) +// CHECK-NOT: getelementptr +// CHECK: call ptr @llvm.preserve.array.access.index.p0.p0(ptr elementtype([3 x %struct.s1]) %{{[0-9a-z]+}}, i32 0, i32 1) +// CHECK-NOT: getelementptr +// CHECK: call ptr @llvm.preserve.array.access.index.p0.p0(ptr elementtype([3 x %struct.s1]) %{{[0-9a-z]+}}, i32 1, i32 2) +// CHECK-NOT: getelementptr +// CHECK: call ptr @llvm.preserve.struct.access.index.p0.p0(ptr elementtype(%struct.s1) %{{[0-9a-z]+}}, i32 1, i32 1) + +int test5(__s2 *arg) { return arg->i[1][2].b; } + +// CHECK-LABEL: @test5 +// CHECK-NOT: getelementptr +// CHECK: call ptr @llvm.preserve.struct.access.index.p0.p0(ptr elementtype(%struct.s2) %{{[0-9a-z]+}}, i32 4, i32 4) +// CHECK-NOT: getelementptr +// CHECK: call ptr @llvm.preserve.array.access.index.p0.p0(ptr elementtype([3 x ptr]) %{{[0-9a-z]+}}, i32 1, i32 1) +// CHECK-NOT: getelementptr +// CHECK: call ptr @llvm.preserve.array.access.index.p0.p0(ptr elementtype(%struct.s1) %{{[0-9a-z]+}}, i32 0, i32 2) +// CHECK-NOT: getelementptr +// CHECK: call ptr @llvm.preserve.struct.access.index.p0.p0(ptr elementtype(%struct.s1) %{{[0-9a-z]+}}, i32 1, i32 1) + +int test6(__s2 *arg) { return arg->j[1][2].b; } + +// CHECK-LABEL: @test6 +// CHECK-NOT: getelementptr +// CHECK: call ptr @llvm.preserve.struct.access.index.p0.p0(ptr elementtype(%struct.s2) %{{[0-9a-z]+}}, i32 5, i32 5) +// CHECK-NOT: getelementptr +// CHECK: call ptr @llvm.preserve.array.access.index.p0.p0(ptr elementtype([2 x [3 x %struct.s1]]) %{{[0-9a-z]+}}, i32 1, i32 1) +// CHECK-NOT: getelementptr +// CHECK: call ptr @llvm.preserve.array.access.index.p0.p0(ptr elementtype([3 x %struct.s1]) %{{[0-9a-z]+}}, i32 1, i32 2) +// CHECK-NOT: getelementptr +// CHECK: call ptr @llvm.preserve.struct.access.index.p0.p0(ptr elementtype(%struct.s1) %{{[0-9a-z]+}}, i32 1, i32 1) + +int test7(__s2 *arg) { return arg->k[1][2].b; } + +// CHECK-LABEL: @test7 +// CHECK-NOT: getelementptr +// CHECK: call ptr @llvm.preserve.struct.access.index.p0.p0(ptr elementtype(%struct.s2) %{{[0-9a-z]+}}, i32 6, i32 6) +// CHECK-NOT: getelementptr +// CHECK: call ptr @llvm.preserve.array.access.index.p0.p0(ptr elementtype([2 x [3 x %struct.s1]]) %{{[0-9a-z]+}}, i32 1, i32 1) +// CHECK-NOT: getelementptr +// CHECK: call ptr @llvm.preserve.array.access.index.p0.p0(ptr elementtype([3 x %struct.s1]) %{{[0-9a-z]+}}, i32 1, i32 2) +// CHECK-NOT: getelementptr +// CHECK: call ptr @llvm.preserve.struct.access.index.p0.p0(ptr elementtype(%struct.s1) %{{[0-9a-z]+}}, i32 1, i32 1) + +// struct -> array -> union -> array -> struct +int test8(struct s3 *arg) { return arg->o[2][1].m[1][2].b; } + +// CHECK-LABEL: @test8 +// CHECK-NOT: getelementptr +// CHECK: call ptr @llvm.preserve.struct.access.index.p0.p0(ptr elementtype(%struct.s3) %{{[0-9a-z]+}}, i32 1, i32 1) +// CHECK-NOT: getelementptr +// CHECK: call ptr @llvm.preserve.array.access.index.p0.p0(ptr elementtype([3 x [2 x %union.u2]]) %{{[0-9a-z]+}}, i32 1, i32 2) +// CHECK-NOT: getelementptr +// CHECK: call ptr @llvm.preserve.array.access.index.p0.p0(ptr elementtype([2 x %union.u2]) %{{[0-9a-z]+}}, i32 1, i32 1) +// CHECK-NOT: getelementptr +// CHECK: call ptr @llvm.preserve.union.access.index.p0.p0(ptr %{{[0-9a-z]+}}, i32 1) +// CHECK-NOT: getelementptr +// CHECK: call ptr @llvm.preserve.array.access.index.p0.p0(ptr elementtype([2 x [3 x %struct.s1]]) %{{[0-9a-z]+}}, i32 1, i32 1) +// CHECK-NOT: getelementptr +// CHECK: call ptr @llvm.preserve.array.access.index.p0.p0(ptr elementtype([3 x %struct.s1]) %{{[0-9a-z]+}}, i32 1, i32 2) +// CHECK-NOT: getelementptr +// CHECK: call ptr @llvm.preserve.struct.access.index.p0.p0(ptr elementtype(%struct.s1) %{{[0-9a-z]+}}, i32 1, i32 1) + +// A variable index cannot be preserved, but later constant subscripts can. +int test9(__s2 *arg, int n) { return arg->f[n][2].b; } + +// CHECK-LABEL: @test9 +// CHECK: call ptr @llvm.preserve.struct.access.index.p0.p0(ptr elementtype(%struct.s2) %{{[0-9a-z]+}}, i32 1, i32 1) +// CHECK: getelementptr inbounds [2 x [3 x %struct.s1]], ptr %{{[0-9a-z]+}}, i64 0, i64 %{{[0-9a-z]+}} +// CHECK: call ptr @llvm.preserve.array.access.index.p0.p0(ptr elementtype([3 x %struct.s1]) %{{[0-9a-z]+}}, i32 1, i32 2) +// CHECK: call ptr @llvm.preserve.struct.access.index.p0.p0(ptr elementtype(%struct.s1) %{{[0-9a-z]+}}, i32 1, i32 1) + +// Parentheses do not change the access chain. +int test10(__s2 *arg) { return (arg->f[1])[2].b; } + +// CHECK-LABEL: @test10 +// CHECK-NOT: getelementptr +// CHECK: call ptr @llvm.preserve.struct.access.index.p0.p0(ptr elementtype(%struct.s2) %{{[0-9a-z]+}}, i32 1, i32 1) +// CHECK-NOT: getelementptr +// CHECK: call ptr @llvm.preserve.array.access.index.p0.p0(ptr elementtype([2 x [3 x %struct.s1]]) %{{[0-9a-z]+}}, i32 1, i32 1) +// CHECK-NOT: getelementptr +// CHECK: call ptr @llvm.preserve.array.access.index.p0.p0(ptr elementtype([3 x %struct.s1]) %{{[0-9a-z]+}}, i32 1, i32 2) +// CHECK-NOT: getelementptr +// CHECK: call ptr @llvm.preserve.struct.access.index.p0.p0(ptr elementtype(%struct.s1) %{{[0-9a-z]+}}, i32 1, i32 1) + +int test11(__s2 *arg) { return (arg->f)[1][2].b; } + +// CHECK-LABEL: @test11 +// CHECK-NOT: getelementptr +// CHECK: call ptr @llvm.preserve.struct.access.index.p0.p0(ptr elementtype(%struct.s2) %{{[0-9a-z]+}}, i32 1, i32 1) +// CHECK-NOT: getelementptr +// CHECK: call ptr @llvm.preserve.array.access.index.p0.p0(ptr elementtype([2 x [3 x %struct.s1]]) %{{[0-9a-z]+}}, i32 1, i32 1) +// CHECK-NOT: getelementptr +// CHECK: call ptr @llvm.preserve.array.access.index.p0.p0(ptr elementtype([3 x %struct.s1]) %{{[0-9a-z]+}}, i32 1, i32 2) +// CHECK-NOT: getelementptr +// CHECK: call ptr @llvm.preserve.struct.access.index.p0.p0(ptr elementtype(%struct.s1) %{{[0-9a-z]+}}, i32 1, i32 1) + +// A variable index in a 3-D array member: the constant subscripts after it are +// still preserved. +int test12(__s2 *arg, int n) { return arg->l[n][2][3].b; } + +// CHECK-LABEL: @test12 +// CHECK: call ptr @llvm.preserve.struct.access.index.p0.p0(ptr elementtype(%struct.s2) %{{[0-9a-z]+}}, i32 7, i32 7) +// CHECK: getelementptr inbounds [2 x [3 x [4 x %struct.s1]]], ptr %{{[0-9a-z]+}}, i64 0, i64 %{{[0-9a-z]+}} +// CHECK-NOT: getelementptr +// CHECK: call ptr @llvm.preserve.array.access.index.p0.p0(ptr elementtype([3 x [4 x %struct.s1]]) %{{[0-9a-z]+}}, i32 1, i32 2) +// CHECK-NOT: getelementptr +// CHECK: call ptr @llvm.preserve.array.access.index.p0.p0(ptr elementtype([4 x %struct.s1]) %{{[0-9a-z]+}}, i32 1, i32 3) +// CHECK-NOT: getelementptr +// CHECK: call ptr @llvm.preserve.struct.access.index.p0.p0(ptr elementtype(%struct.s1) %{{[0-9a-z]+}}, i32 1, i32 1) diff --git a/llvm/test/CodeGen/BPF/CORE/offset-reloc-subarray-record.ll b/llvm/test/CodeGen/BPF/CORE/offset-reloc-subarray-record.ll new file mode 100644 index 00000000000000..2e25097ff79199 --- /dev/null +++ b/llvm/test/CodeGen/BPF/CORE/offset-reloc-subarray-record.ll @@ -0,0 +1,469 @@ +; RUN: opt -O2 %s | llc -filetype=obj -o - | \ +; RUN: llvm-objdump --no-addresses --no-show-raw-insn --no-print-imm-hex -dr - | \ +; RUN: FileCheck %s --implicit-check-not=CO-RE + +; A record inside a multi-dimensional array member stays in the access chain, +; so each access needs one relocation rooted at the outer record. This holds +; through qualifiers, typedefs, array element typedefs and nested arrays. +; +; Source: +; #define __pai __attribute__((preserve_access_index)) +; struct S { long x; int y; } __pai; +; typedef const volatile struct S cvS; +; typedef struct { long x; int y; } __pai Anon; +; typedef struct S Arr2[2][3]; +; typedef struct S Row[3]; +; union U { int i; const struct S s; } __pai; +; union V { long l; const struct S m[2][3]; } __pai; +; typedef union V Vrow[2]; +; struct T { int pad; struct S a[2][3]; volatile union U b[2][3]; cvS c[2][3]; Anon d[2][3]; const Arr2 e; Row f[2]; const Vrow g[3]; struct S h[2][3][4]; } __pai; +; typedef const struct T cT; +; int rec(cT *t) { return t->a[1][2].y; } +; int un(cT *t) { return t->b[1][2].s.y; } +; int cv(cT *t) { return t->c[1][2].y; } +; int anon(cT *t) { return t->d[1][2].y; } +; int arr2(cT *t) { return t->e[1][2].y; } +; int row(cT *t) { return t->f[1][2].y; } +; int nest(cT *t) { return t->g[2][1].m[1][2].y; } +; unsigned nest_sz(cT *t) { return __builtin_preserve_field_info(t->g[2][1].m[1], 1); } +; int var(cT *t, int n) { return t->a[n][2].y; } +; int var3(cT *t, int n) { return t->h[n][2][3].y; } +; Compilation flag: +; clang -target bpf -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes test.c + +; CHECK-LABEL: <rec>: +; CHECK: w0 = *(u32 *)(r1 + 96) +; CHECK-NEXT: CO-RE <byte_off> [{{[0-9]+}}] typedef cT::a[1][2].y (0:1:1:2:1) +; CHECK-LABEL: <un>: +; CHECK: w0 = *(u32 *)(r1 + 192) +; CHECK-NEXT: CO-RE <byte_off> [{{[0-9]+}}] typedef cT::b[1][2].s.y (0:2:1:2:1:1) +; CHECK-LABEL: <cv>: +; CHECK: w0 = *(u32 *)(r1 + 288) +; CHECK-NEXT: CO-RE <byte_off> [{{[0-9]+}}] typedef cT::c[1][2].y (0:3:1:2:1) +; CHECK-LABEL: <anon>: +; CHECK: w0 = *(u32 *)(r1 + 384) +; CHECK-NEXT: CO-RE <byte_off> [{{[0-9]+}}] typedef cT::d[1][2].y (0:4:1:2:1) +; CHECK-LABEL: <arr2>: +; CHECK: w0 = *(u32 *)(r1 + 480) +; CHECK-NEXT: CO-RE <byte_off> [{{[0-9]+}}] typedef cT::e[1][2].y (0:5:1:2:1) +; CHECK-LABEL: <row>: +; CHECK: w0 = *(u32 *)(r1 + 576) +; CHECK-NEXT: CO-RE <byte_off> [{{[0-9]+}}] typedef cT::f[1][2].y (0:6:1:2:1) +; CHECK-LABEL: <nest>: +; CHECK: w0 = *(u32 *)(r1 + 1152) +; CHECK-NEXT: CO-RE <byte_off> [{{[0-9]+}}] typedef cT::g[2][1].m[1][2].y (0:7:2:1:1:1:2:1) +; CHECK-LABEL: <nest_sz>: +; CHECK: r0 = 48 +; CHECK-NEXT: CO-RE <byte_sz> [{{[0-9]+}}] typedef cT::g[2][1].m[1] (0:7:2:1:1:1) +; The variable subscript [n] is not relocated, but the constant [2] after it +; is part of the relocation rooted at struct S. +; CHECK-LABEL: <var>: +; CHECK: r{{[0-9]+}} = 8 +; CHECK-NEXT: CO-RE <byte_off> [{{[0-9]+}}] typedef cT::a (0:1) +; CHECK: w0 = *(u32 *)(r1 + 40) +; CHECK-NEXT: CO-RE <byte_off> [{{[0-9]+}}] struct S::[2].y (2:1) +; In a 3-D array, both constant subscripts after [n] are folded into one +; index, 2 * 4 + 3 = 11. +; CHECK-LABEL: <var3>: +; CHECK: r{{[0-9]+}} = 1160 +; CHECK-NEXT: CO-RE <byte_off> [{{[0-9]+}}] typedef cT::h (0:8) +; CHECK: w0 = *(u32 *)(r1 + 184) +; CHECK-NEXT: CO-RE <byte_off> [{{[0-9]+}}] struct S::[11].y (11:1) + +source_filename = "test.c" +target triple = "bpf" + +%struct.T = type { i32, [2 x [3 x %struct.S]], [2 x [3 x %union.U]], [2 x [3 x %struct.S]], [2 x [3 x %struct.Anon]], [2 x [3 x %struct.S]], [2 x [3 x %struct.S]], [3 x [2 x %union.V]], [2 x [3 x [4 x %struct.S]]] } +%union.U = type { %struct.S } +%struct.S = type { i64, i32 } +%struct.Anon = type { i64, i32 } +%union.V = type { [2 x [3 x %struct.S]] } + +; Function Attrs: nounwind +define dso_local i32 @rec(ptr noundef %0) #0 !dbg !93 { + %2 = alloca ptr, align 8 + store ptr %0, ptr %2, align 8, !tbaa !99 + #dbg_declare(ptr %2, !98, !DIExpression(), !102) + %3 = load ptr, ptr %2, align 8, !dbg !103, !tbaa !99 + %4 = call ptr @llvm.preserve.struct.access.index.p0.p0(ptr elementtype(%struct.T) %3, i32 1, i32 1), !dbg !104, !llvm.preserve.access.index !3 + %5 = call ptr @llvm.preserve.array.access.index.p0.p0(ptr elementtype([2 x [3 x %struct.S]]) %4, i32 1, i32 1), !dbg !103, !llvm.preserve.access.index !62 + %6 = call ptr @llvm.preserve.array.access.index.p0.p0(ptr elementtype([3 x %struct.S]) %5, i32 1, i32 2), !dbg !103, !llvm.preserve.access.index !63 + %7 = call ptr @llvm.preserve.struct.access.index.p0.p0(ptr elementtype(%struct.S) %6, i32 1, i32 1), !dbg !105, !llvm.preserve.access.index !26 + %8 = load i32, ptr %7, align 8, !dbg !106, !tbaa !107 + ret i32 %8, !dbg !110 +} + +; Function Attrs: nocallback nofree nosync nounwind willreturn memory(none) +declare ptr @llvm.preserve.struct.access.index.p0.p0(ptr, i32 immarg, i32 immarg) #1 + +; Function Attrs: nocallback nofree nosync nounwind willreturn memory(none) +declare ptr @llvm.preserve.array.access.index.p0.p0(ptr, i32 immarg, i32 immarg) #1 + +; Function Attrs: nounwind +define dso_local i32 @un(ptr noundef %0) #0 !dbg !111 { + %2 = alloca ptr, align 8 + store ptr %0, ptr %2, align 8, !tbaa !99 + #dbg_declare(ptr %2, !113, !DIExpression(), !114) + %3 = load ptr, ptr %2, align 8, !dbg !115, !tbaa !99 + %4 = call ptr @llvm.preserve.struct.access.index.p0.p0(ptr elementtype(%struct.T) %3, i32 2, i32 2), !dbg !116, !llvm.preserve.access.index !3 + %5 = call ptr @llvm.preserve.array.access.index.p0.p0(ptr elementtype([2 x [3 x %union.U]]) %4, i32 1, i32 1), !dbg !115, !llvm.preserve.access.index !64 + %6 = call ptr @llvm.preserve.array.access.index.p0.p0(ptr elementtype([3 x %union.U]) %5, i32 1, i32 2), !dbg !115, !llvm.preserve.access.index !66 + %7 = call ptr @llvm.preserve.union.access.index.p0.p0(ptr %6, i32 1), !dbg !117, !llvm.preserve.access.index !118 + %8 = call ptr @llvm.preserve.struct.access.index.p0.p0(ptr elementtype(%struct.S) %7, i32 1, i32 1), !dbg !119, !llvm.preserve.access.index !26 + %9 = load volatile i32, ptr %8, align 8, !dbg !120, !tbaa !121 + ret i32 %9, !dbg !122 +} + +; Function Attrs: nocallback nofree nosync nounwind willreturn memory(none) +declare ptr @llvm.preserve.union.access.index.p0.p0(ptr, i32 immarg) #1 + +; Function Attrs: nounwind +define dso_local i32 @cv(ptr noundef %0) #0 !dbg !123 { + %2 = alloca ptr, align 8 + store ptr %0, ptr %2, align 8, !tbaa !99 + #dbg_declare(ptr %2, !125, !DIExpression(), !126) + %3 = load ptr, ptr %2, align 8, !dbg !127, !tbaa !99 + %4 = call ptr @llvm.preserve.struct.access.index.p0.p0(ptr elementtype(%struct.T) %3, i32 3, i32 3), !dbg !128, !llvm.preserve.access.index !3 + %5 = call ptr @llvm.preserve.array.access.index.p0.p0(ptr elementtype([2 x [3 x %struct.S]]) %4, i32 1, i32 1), !dbg !127, !llvm.preserve.access.index !28 + %6 = call ptr @llvm.preserve.array.access.index.p0.p0(ptr elementtype([3 x %struct.S]) %5, i32 1, i32 2), !dbg !127, !llvm.preserve.access.index !69 + %7 = call ptr @llvm.preserve.struct.access.index.p0.p0(ptr elementtype(%struct.S) %6, i32 1, i32 1), !dbg !129, !llvm.preserve.access.index !29 + %8 = load volatile i32, ptr %7, align 8, !dbg !130, !tbaa !107 + ret i32 %8, !dbg !131 +} + +; Function Attrs: nounwind +define dso_local i32 @anon(ptr noundef %0) #0 !dbg !132 { + %2 = alloca ptr, align 8 + store ptr %0, ptr %2, align 8, !tbaa !99 + #dbg_declare(ptr %2, !134, !DIExpression(), !135) + %3 = load ptr, ptr %2, align 8, !dbg !136, !tbaa !99 + %4 = call ptr @llvm.preserve.struct.access.index.p0.p0(ptr elementtype(%struct.T) %3, i32 4, i32 4), !dbg !137, !llvm.preserve.access.index !3 + %5 = call ptr @llvm.preserve.array.access.index.p0.p0(ptr elementtype([2 x [3 x %struct.Anon]]) %4, i32 1, i32 1), !dbg !136, !llvm.preserve.access.index !70 + %6 = call ptr @llvm.preserve.array.access.index.p0.p0(ptr elementtype([3 x %struct.Anon]) %5, i32 1, i32 2), !dbg !136, !llvm.preserve.access.index !71 + %7 = call ptr @llvm.preserve.struct.access.index.p0.p0(ptr elementtype(%struct.Anon) %6, i32 1, i32 1), !dbg !138, !llvm.preserve.access.index !73 + %8 = load i32, ptr %7, align 8, !dbg !139, !tbaa !140 + ret i32 %8, !dbg !142 +} + +; Function Attrs: nounwind +define dso_local i32 @arr2(ptr noundef %0) #0 !dbg !143 { + %2 = alloca ptr, align 8 + store ptr %0, ptr %2, align 8, !tbaa !99 + #dbg_declare(ptr %2, !145, !DIExpression(), !146) + %3 = load ptr, ptr %2, align 8, !dbg !147, !tbaa !99 + %4 = call ptr @llvm.preserve.struct.access.index.p0.p0(ptr elementtype(%struct.T) %3, i32 5, i32 5), !dbg !148, !llvm.preserve.access.index !3 + %5 = call ptr @llvm.preserve.array.access.index.p0.p0(ptr elementtype([2 x [3 x %struct.S]]) %4, i32 1, i32 1), !dbg !147, !llvm.preserve.access.index !40 + %6 = call ptr @llvm.preserve.array.access.index.p0.p0(ptr elementtype([3 x %struct.S]) %5, i32 1, i32 2), !dbg !147, !llvm.preserve.access.index !63 + %7 = call ptr @llvm.preserve.struct.access.index.p0.p0(ptr elementtype(%struct.S) %6, i32 1, i32 1), !dbg !149, !llvm.preserve.access.index !26 + %8 = load i32, ptr %7, align 8, !dbg !150, !tbaa !107 + ret i32 %8, !dbg !151 +} + +; Function Attrs: nounwind +define dso_local i32 @row(ptr noundef %0) #0 !dbg !152 { + %2 = alloca ptr, align 8 + store ptr %0, ptr %2, align 8, !tbaa !99 + #dbg_declare(ptr %2, !154, !DIExpression(), !155) + %3 = load ptr, ptr %2, align 8, !dbg !156, !tbaa !99 + %4 = call ptr @llvm.preserve.struct.access.index.p0.p0(ptr elementtype(%struct.T) %3, i32 6, i32 6), !dbg !157, !llvm.preserve.access.index !3 + %5 = call ptr @llvm.preserve.array.access.index.p0.p0(ptr elementtype([2 x [3 x %struct.S]]) %4, i32 1, i32 1), !dbg !156, !llvm.preserve.access.index !74 + %6 = call ptr @llvm.preserve.array.access.index.p0.p0(ptr elementtype([3 x %struct.S]) %5, i32 1, i32 2), !dbg !156, !llvm.preserve.access.index !75 + %7 = call ptr @llvm.preserve.struct.access.index.p0.p0(ptr elementtype(%struct.S) %6, i32 1, i32 1), !dbg !158, !llvm.preserve.access.index !26 + %8 = load i32, ptr %7, align 8, !dbg !159, !tbaa !107 + ret i32 %8, !dbg !160 +} + +; Function Attrs: nounwind +define dso_local i32 @nest(ptr noundef %0) #0 !dbg !161 { + %2 = alloca ptr, align 8 + store ptr %0, ptr %2, align 8, !tbaa !99 + #dbg_declare(ptr %2, !163, !DIExpression(), !164) + %3 = load ptr, ptr %2, align 8, !dbg !165, !tbaa !99 + %4 = call ptr @llvm.preserve.struct.access.index.p0.p0(ptr elementtype(%struct.T) %3, i32 7, i32 7), !dbg !166, !llvm.preserve.access.index !3 + %5 = call ptr @llvm.preserve.array.access.index.p0.p0(ptr elementtype([3 x [2 x %union.V]]) %4, i32 1, i32 2), !dbg !165, !llvm.preserve.access.index !49 + %6 = call ptr @llvm.preserve.array.access.index.p0.p0(ptr elementtype([2 x %union.V]) %5, i32 1, i32 1), !dbg !165, !llvm.preserve.access.index !50 + %7 = call ptr @llvm.preserve.union.access.index.p0.p0(ptr %6, i32 1), !dbg !167, !llvm.preserve.access.index !168 + %8 = call ptr @llvm.preserve.array.access.index.p0.p0(ptr elementtype([2 x [3 x %struct.S]]) %7, i32 1, i32 1), !dbg !165, !llvm.preserve.access.index !57 + %9 = call ptr @llvm.preserve.array.access.index.p0.p0(ptr elementtype([3 x %struct.S]) %8, i32 1, i32 2), !dbg !165, !llvm.preserve.access.index !76 + %10 = call ptr @llvm.preserve.struct.access.index.p0.p0(ptr elementtype(%struct.S) %9, i32 1, i32 1), !dbg !169, !llvm.preserve.access.index !26 + %11 = load i32, ptr %10, align 8, !dbg !170, !tbaa !121 + ret i32 %11, !dbg !171 +} + +; Function Attrs: nounwind +define dso_local i32 @nest_sz(ptr noundef %0) #0 !dbg !172 { + %2 = alloca ptr, align 8 + store ptr %0, ptr %2, align 8, !tbaa !99 + #dbg_declare(ptr %2, !177, !DIExpression(), !178) + %3 = load ptr, ptr %2, align 8, !dbg !179, !tbaa !99 + %4 = call ptr @llvm.preserve.struct.access.index.p0.p0(ptr elementtype(%struct.T) %3, i32 7, i32 7), !dbg !180, !llvm.preserve.access.index !3 + %5 = call ptr @llvm.preserve.array.access.index.p0.p0(ptr elementtype([3 x [2 x %union.V]]) %4, i32 1, i32 2), !dbg !179, !llvm.preserve.access.index !49 + %6 = call ptr @llvm.preserve.array.access.index.p0.p0(ptr elementtype([2 x %union.V]) %5, i32 1, i32 1), !dbg !179, !llvm.preserve.access.index !50 + %7 = call ptr @llvm.preserve.union.access.index.p0.p0(ptr %6, i32 1), !dbg !181, !llvm.preserve.access.index !168 + %8 = call ptr @llvm.preserve.array.access.index.p0.p0(ptr elementtype([2 x [3 x %struct.S]]) %7, i32 1, i32 1), !dbg !179, !llvm.preserve.access.index !57 + %9 = call i32 @llvm.bpf.preserve.field.info.p0(ptr %8, i64 1), !dbg !182 + ret i32 %9, !dbg !183 +} + +; Function Attrs: nounwind memory(none) +declare i32 @llvm.bpf.preserve.field.info.p0(ptr, i64 immarg) #2 + +; Function Attrs: nounwind +define dso_local i32 @var(ptr noundef %0, i32 noundef %1) #0 !dbg !184 { + %3 = alloca ptr, align 8 + %4 = alloca i32, align 4 + store ptr %0, ptr %3, align 8, !tbaa !99 + #dbg_declare(ptr %3, !188, !DIExpression(), !190) + store i32 %1, ptr %4, align 4, !tbaa !191 + #dbg_declare(ptr %4, !189, !DIExpression(), !192) + %5 = load ptr, ptr %3, align 8, !dbg !193, !tbaa !99 + %6 = call ptr @llvm.preserve.struct.access.index.p0.p0(ptr elementtype(%struct.T) %5, i32 1, i32 1), !dbg !194, !llvm.preserve.access.index !3 + %7 = load i32, ptr %4, align 4, !dbg !195, !tbaa !191 + %8 = sext i32 %7 to i64, !dbg !193 + %9 = getelementptr inbounds [2 x [3 x %struct.S]], ptr %6, i64 0, i64 %8, !dbg !193 + %10 = call ptr @llvm.preserve.array.access.index.p0.p0(ptr elementtype([3 x %struct.S]) %9, i32 1, i32 2), !dbg !193, !llvm.preserve.access.index !63 + %11 = call ptr @llvm.preserve.struct.access.index.p0.p0(ptr elementtype(%struct.S) %10, i32 1, i32 1), !dbg !196, !llvm.preserve.access.index !26 + %12 = load i32, ptr %11, align 8, !dbg !197, !tbaa !107 + ret i32 %12, !dbg !198 +} + +; Function Attrs: nounwind +define dso_local i32 @var3(ptr noundef %0, i32 noundef %1) #0 !dbg !199 { + %3 = alloca ptr, align 8 + %4 = alloca i32, align 4 + store ptr %0, ptr %3, align 8, !tbaa !99 + #dbg_declare(ptr %3, !201, !DIExpression(), !203) + store i32 %1, ptr %4, align 4, !tbaa !191 + #dbg_declare(ptr %4, !202, !DIExpression(), !204) + %5 = load ptr, ptr %3, align 8, !dbg !205, !tbaa !99 + %6 = call ptr @llvm.preserve.struct.access.index.p0.p0(ptr elementtype(%struct.T) %5, i32 8, i32 8), !dbg !206, !llvm.preserve.access.index !3 + %7 = load i32, ptr %4, align 4, !dbg !207, !tbaa !191 + %8 = sext i32 %7 to i64, !dbg !205 + %9 = getelementptr inbounds [2 x [3 x [4 x %struct.S]]], ptr %6, i64 0, i64 %8, !dbg !205 + %10 = call ptr @llvm.preserve.array.access.index.p0.p0(ptr elementtype([3 x [4 x %struct.S]]) %9, i32 1, i32 2), !dbg !205, !llvm.preserve.access.index !77 + %11 = call ptr @llvm.preserve.array.access.index.p0.p0(ptr elementtype([4 x %struct.S]) %10, i32 1, i32 3), !dbg !205, !llvm.preserve.access.index !80 + %12 = call ptr @llvm.preserve.struct.access.index.p0.p0(ptr elementtype(%struct.S) %11, i32 1, i32 1), !dbg !208, !llvm.preserve.access.index !26 + %13 = load i32, ptr %12, align 8, !dbg !209, !tbaa !107 + ret i32 %13, !dbg !210 +} + +attributes #0 = { nounwind "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" } +attributes #1 = { nocallback nofree nosync nounwind willreturn memory(none) } +attributes #2 = { nounwind memory(none) } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!83, !84, !85, !86} +!llvm.ident = !{!87} +!llvm.errno.tbaa = !{!88} + +!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, retainedTypes: !2) +!1 = !DIFile(filename: "test.c", directory: "/") +!2 = !{!3, !62, !63, !64, !66, !28, !69, !29, !70, !71, !73, !40, !74, !75, !49, !50, !57, !76, !77, !80} +!3 = !DIDerivedType(tag: DW_TAG_typedef, name: "cT", file: !1, line: 11, baseType: !4) +!4 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !5) +!5 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "T", file: !1, line: 10, size: 12352, elements: !6) +!6 = !{!7, !9, !19, !27, !32, !39, !42, !48, !58} +!7 = !DIDerivedType(tag: DW_TAG_member, name: "pad", scope: !5, file: !1, line: 10, baseType: !8, size: 32) +!8 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!9 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !5, file: !1, line: 10, baseType: !10, size: 768, offset: 64) +!10 = !DICompositeType(tag: DW_TAG_array_type, baseType: !11, size: 768, elements: !16) +!11 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "S", file: !1, line: 2, size: 128, elements: !12) +!12 = !{!13, !15} +!13 = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: !11, file: !1, line: 2, baseType: !14, size: 64) +!14 = !DIBasicType(name: "long", size: 64, encoding: DW_ATE_signed) +!15 = !DIDerivedType(tag: DW_TAG_member, name: "y", scope: !11, file: !1, line: 2, baseType: !8, size: 32, offset: 64) +!16 = !{!17, !18} +!17 = !DISubrange(count: 2) +!18 = !DISubrange(count: 3) +!19 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !5, file: !1, line: 10, baseType: !20, size: 768, offset: 832) +!20 = !DICompositeType(tag: DW_TAG_array_type, baseType: !21, size: 768, elements: !16) +!21 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !22) +!22 = distinct !DICompositeType(tag: DW_TAG_union_type, name: "U", file: !1, line: 7, size: 128, elements: !23) +!23 = !{!24, !25} +!24 = !DIDerivedType(tag: DW_TAG_member, name: "i", scope: !22, file: !1, line: 7, baseType: !8, size: 32) +!25 = !DIDerivedType(tag: DW_TAG_member, name: "s", scope: !22, file: !1, line: 7, baseType: !26, size: 128) +!26 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !11) +!27 = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: !5, file: !1, line: 10, baseType: !28, size: 768, offset: 1600) +!28 = !DICompositeType(tag: DW_TAG_array_type, baseType: !29, size: 768, elements: !16) +!29 = !DIDerivedType(tag: DW_TAG_typedef, name: "cvS", file: !1, line: 3, baseType: !30) +!30 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !31) +!31 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !11) +!32 = !DIDerivedType(tag: DW_TAG_member, name: "d", scope: !5, file: !1, line: 10, baseType: !33, size: 768, offset: 2368) +!33 = !DICompositeType(tag: DW_TAG_array_type, baseType: !34, size: 768, elements: !16) +!34 = !DIDerivedType(tag: DW_TAG_typedef, name: "Anon", file: !1, line: 4, baseType: !35) +!35 = distinct !DICompositeType(tag: DW_TAG_structure_type, file: !1, line: 4, size: 128, elements: !36) +!36 = !{!37, !38} +!37 = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: !35, file: !1, line: 4, baseType: !14, size: 64) +!38 = !DIDerivedType(tag: DW_TAG_member, name: "y", scope: !35, file: !1, line: 4, baseType: !8, size: 32, offset: 64) +!39 = !DIDerivedType(tag: DW_TAG_member, name: "e", scope: !5, file: !1, line: 10, baseType: !40, size: 768, offset: 3136) +!40 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !41) +!41 = !DIDerivedType(tag: DW_TAG_typedef, name: "Arr2", file: !1, line: 5, baseType: !10) +!42 = !DIDerivedType(tag: DW_TAG_member, name: "f", scope: !5, file: !1, line: 10, baseType: !43, size: 768, offset: 3904) +!43 = !DICompositeType(tag: DW_TAG_array_type, baseType: !44, size: 768, elements: !47) +!44 = !DIDerivedType(tag: DW_TAG_typedef, name: "Row", file: !1, line: 6, baseType: !45) +!45 = !DICompositeType(tag: DW_TAG_array_type, baseType: !11, size: 384, elements: !46) +!46 = !{!18} +!47 = !{!17} +!48 = !DIDerivedType(tag: DW_TAG_member, name: "g", scope: !5, file: !1, line: 10, baseType: !49, size: 4608, offset: 4672) +!49 = !DICompositeType(tag: DW_TAG_array_type, baseType: !50, size: 4608, elements: !46) +!50 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !51) +!51 = !DIDerivedType(tag: DW_TAG_typedef, name: "Vrow", file: !1, line: 9, baseType: !52) +!52 = !DICompositeType(tag: DW_TAG_array_type, baseType: !53, size: 1536, elements: !47) +!53 = distinct !DICompositeType(tag: DW_TAG_union_type, name: "V", file: !1, line: 8, size: 768, elements: !54) +!54 = !{!55, !56} +!55 = !DIDerivedType(tag: DW_TAG_member, name: "l", scope: !53, file: !1, line: 8, baseType: !14, size: 64) +!56 = !DIDerivedType(tag: DW_TAG_member, name: "m", scope: !53, file: !1, line: 8, baseType: !57, size: 768) +!57 = !DICompositeType(tag: DW_TAG_array_type, baseType: !26, size: 768, elements: !16) +!58 = !DIDerivedType(tag: DW_TAG_member, name: "h", scope: !5, file: !1, line: 10, baseType: !59, size: 3072, offset: 9280) +!59 = !DICompositeType(tag: DW_TAG_array_type, baseType: !11, size: 3072, elements: !60) +!60 = !{!17, !18, !61} +!61 = !DISubrange(count: 4) +!62 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !10) +!63 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !45) +!64 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !65) +!65 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !20) +!66 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !67) +!67 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !68) +!68 = !DICompositeType(tag: DW_TAG_array_type, baseType: !21, size: 384, elements: !46) +!69 = !DICompositeType(tag: DW_TAG_array_type, baseType: !29, size: 384, elements: !46) +!70 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !33) +!71 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !72) +!72 = !DICompositeType(tag: DW_TAG_array_type, baseType: !34, size: 384, elements: !46) +!73 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !34) +!74 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !43) +!75 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !44) +!76 = !DICompositeType(tag: DW_TAG_array_type, baseType: !26, size: 384, elements: !46) +!77 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !78) +!78 = !DICompositeType(tag: DW_TAG_array_type, baseType: !11, size: 1536, elements: !79) +!79 = !{!18, !61} +!80 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !81) +!81 = !DICompositeType(tag: DW_TAG_array_type, baseType: !11, size: 512, elements: !82) +!82 = !{!61} +!83 = !{i32 7, !"Dwarf Version", i32 5} +!84 = !{i32 2, !"Debug Info Version", i32 3} +!85 = !{i32 2, !"debugger-tuning", !"gdb"} +!86 = !{i32 7, !"frame-pointer", i32 2} +!87 = !{!"clang version 24.0.0git"} +!88 = !{!89, !90, i64 0} +!89 = !{!"__libc_errno", !90, i64 0} +!90 = !{!"int", !91, i64 0} +!91 = !{!"omnipotent char", !92, i64 0} +!92 = !{!"Simple C/C++ TBAA"} +!93 = distinct !DISubprogram(name: "rec", scope: !1, file: !1, line: 12, type: !94, scopeLine: 12, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !97, keyInstructions: true) +!94 = !DISubroutineType(types: !95) +!95 = !{!8, !96} +!96 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !3, size: 64) +!97 = !{!98} +!98 = !DILocalVariable(name: "t", arg: 1, scope: !93, file: !1, line: 12, type: !96) +!99 = !{!100, !100, i64 0} +!100 = !{!"p1 _ZTS1T", !101, i64 0} +!101 = !{!"any pointer", !91, i64 0} +!102 = !DILocation(line: 12, column: 13, scope: !93) +!103 = !DILocation(line: 12, column: 25, scope: !93) +!104 = !DILocation(line: 12, column: 28, scope: !93) +!105 = !DILocation(line: 12, column: 36, scope: !93) +!106 = !DILocation(line: 12, column: 36, scope: !93, atomGroup: 1, atomRank: 2) +!107 = !{!108, !90, i64 8} +!108 = !{!"S", !109, i64 0, !90, i64 8} +!109 = !{!"long", !91, i64 0} +!110 = !DILocation(line: 12, column: 18, scope: !93, atomGroup: 1, atomRank: 1) +!111 = distinct !DISubprogram(name: "un", scope: !1, file: !1, line: 13, type: !94, scopeLine: 13, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !112, keyInstructions: true) +!112 = !{!113} +!113 = !DILocalVariable(name: "t", arg: 1, scope: !111, file: !1, line: 13, type: !96) +!114 = !DILocation(line: 13, column: 12, scope: !111) +!115 = !DILocation(line: 13, column: 24, scope: !111) +!116 = !DILocation(line: 13, column: 27, scope: !111) +!117 = !DILocation(line: 13, column: 35, scope: !111) +!118 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !21) +!119 = !DILocation(line: 13, column: 37, scope: !111) +!120 = !DILocation(line: 13, column: 37, scope: !111, atomGroup: 1, atomRank: 2) +!121 = !{!91, !91, i64 0} +!122 = !DILocation(line: 13, column: 17, scope: !111, atomGroup: 1, atomRank: 1) +!123 = distinct !DISubprogram(name: "cv", scope: !1, file: !1, line: 14, type: !94, scopeLine: 14, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !124, keyInstructions: true) +!124 = !{!125} +!125 = !DILocalVariable(name: "t", arg: 1, scope: !123, file: !1, line: 14, type: !96) +!126 = !DILocation(line: 14, column: 12, scope: !123) +!127 = !DILocation(line: 14, column: 24, scope: !123) +!128 = !DILocation(line: 14, column: 27, scope: !123) +!129 = !DILocation(line: 14, column: 35, scope: !123) +!130 = !DILocation(line: 14, column: 35, scope: !123, atomGroup: 1, atomRank: 2) +!131 = !DILocation(line: 14, column: 17, scope: !123, atomGroup: 1, atomRank: 1) +!132 = distinct !DISubprogram(name: "anon", scope: !1, file: !1, line: 15, type: !94, scopeLine: 15, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !133, keyInstructions: true) +!133 = !{!134} +!134 = !DILocalVariable(name: "t", arg: 1, scope: !132, file: !1, line: 15, type: !96) +!135 = !DILocation(line: 15, column: 14, scope: !132) +!136 = !DILocation(line: 15, column: 26, scope: !132) +!137 = !DILocation(line: 15, column: 29, scope: !132) +!138 = !DILocation(line: 15, column: 37, scope: !132) +!139 = !DILocation(line: 15, column: 37, scope: !132, atomGroup: 1, atomRank: 2) +!140 = !{!141, !90, i64 8} +!141 = !{!"", !109, i64 0, !90, i64 8} +!142 = !DILocation(line: 15, column: 19, scope: !132, atomGroup: 1, atomRank: 1) +!143 = distinct !DISubprogram(name: "arr2", scope: !1, file: !1, line: 16, type: !94, scopeLine: 16, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !144, keyInstructions: true) +!144 = !{!145} +!145 = !DILocalVariable(name: "t", arg: 1, scope: !143, file: !1, line: 16, type: !96) +!146 = !DILocation(line: 16, column: 14, scope: !143) +!147 = !DILocation(line: 16, column: 26, scope: !143) +!148 = !DILocation(line: 16, column: 29, scope: !143) +!149 = !DILocation(line: 16, column: 37, scope: !143) +!150 = !DILocation(line: 16, column: 37, scope: !143, atomGroup: 1, atomRank: 2) +!151 = !DILocation(line: 16, column: 19, scope: !143, atomGroup: 1, atomRank: 1) +!152 = distinct !DISubprogram(name: "row", scope: !1, file: !1, line: 17, type: !94, scopeLine: 17, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !153, keyInstructions: true) +!153 = !{!154} +!154 = !DILocalVariable(name: "t", arg: 1, scope: !152, file: !1, line: 17, type: !96) +!155 = !DILocation(line: 17, column: 13, scope: !152) +!156 = !DILocation(line: 17, column: 25, scope: !152) +!157 = !DILocation(line: 17, column: 28, scope: !152) +!158 = !DILocation(line: 17, column: 36, scope: !152) +!159 = !DILocation(line: 17, column: 36, scope: !152, atomGroup: 1, atomRank: 2) +!160 = !DILocation(line: 17, column: 18, scope: !152, atomGroup: 1, atomRank: 1) +!161 = distinct !DISubprogram(name: "nest", scope: !1, file: !1, line: 18, type: !94, scopeLine: 18, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !162, keyInstructions: true) +!162 = !{!163} +!163 = !DILocalVariable(name: "t", arg: 1, scope: !161, file: !1, line: 18, type: !96) +!164 = !DILocation(line: 18, column: 14, scope: !161) +!165 = !DILocation(line: 18, column: 26, scope: !161) +!166 = !DILocation(line: 18, column: 29, scope: !161) +!167 = !DILocation(line: 18, column: 37, scope: !161) +!168 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !53) +!169 = !DILocation(line: 18, column: 45, scope: !161) +!170 = !DILocation(line: 18, column: 45, scope: !161, atomGroup: 1, atomRank: 2) +!171 = !DILocation(line: 18, column: 19, scope: !161, atomGroup: 1, atomRank: 1) +!172 = distinct !DISubprogram(name: "nest_sz", scope: !1, file: !1, line: 19, type: !173, scopeLine: 19, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !176, keyInstructions: true) +!173 = !DISubroutineType(types: !174) +!174 = !{!175, !96} +!175 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned) +!176 = !{!177} +!177 = !DILocalVariable(name: "t", arg: 1, scope: !172, file: !1, line: 19, type: !96) +!178 = !DILocation(line: 19, column: 22, scope: !172) +!179 = !DILocation(line: 19, column: 64, scope: !172) +!180 = !DILocation(line: 19, column: 67, scope: !172) +!181 = !DILocation(line: 19, column: 75, scope: !172) +!182 = !DILocation(line: 19, column: 34, scope: !172, atomGroup: 1, atomRank: 2) +!183 = !DILocation(line: 19, column: 27, scope: !172, atomGroup: 1, atomRank: 1) +!184 = distinct !DISubprogram(name: "var", scope: !1, file: !1, line: 20, type: !185, scopeLine: 20, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !187, keyInstructions: true) +!185 = !DISubroutineType(types: !186) +!186 = !{!8, !96, !8} +!187 = !{!188, !189} +!188 = !DILocalVariable(name: "t", arg: 1, scope: !184, file: !1, line: 20, type: !96) +!189 = !DILocalVariable(name: "n", arg: 2, scope: !184, file: !1, line: 20, type: !8) +!190 = !DILocation(line: 20, column: 13, scope: !184) +!191 = !{!90, !90, i64 0} +!192 = !DILocation(line: 20, column: 20, scope: !184) +!193 = !DILocation(line: 20, column: 32, scope: !184) +!194 = !DILocation(line: 20, column: 35, scope: !184) +!195 = !DILocation(line: 20, column: 37, scope: !184) +!196 = !DILocation(line: 20, column: 43, scope: !184) +!197 = !DILocation(line: 20, column: 43, scope: !184, atomGroup: 1, atomRank: 2) +!198 = !DILocation(line: 20, column: 25, scope: !184, atomGroup: 1, atomRank: 1) +!199 = distinct !DISubprogram(name: "var3", scope: !1, file: !1, line: 21, type: !185, scopeLine: 21, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !200, keyInstructions: true) +!200 = !{!201, !202} +!201 = !DILocalVariable(name: "t", arg: 1, scope: !199, file: !1, line: 21, type: !96) +!202 = !DILocalVariable(name: "n", arg: 2, scope: !199, file: !1, line: 21, type: !8) +!203 = !DILocation(line: 21, column: 14, scope: !199) +!204 = !DILocation(line: 21, column: 21, scope: !199) +!205 = !DILocation(line: 21, column: 33, scope: !199) +!206 = !DILocation(line: 21, column: 36, scope: !199) +!207 = !DILocation(line: 21, column: 38, scope: !199) +!208 = !DILocation(line: 21, column: 47, scope: !199) +!209 = !DILocation(line: 21, column: 47, scope: !199, atomGroup: 1, atomRank: 2) +!210 = !DILocation(line: 21, column: 26, scope: !199, atomGroup: 1, atomRank: 1) _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
