From 5eb29c8b23b652b8dd8988621f5c91191b13ffe3 Mon Sep 17 00:00:00 2001 From: Yonghong Song Date: Fri, 2 Aug 2019 21:28:28 +0000 Subject: [PATCH] [BPF] annotate DIType metadata for builtin preseve_array_access_index() Previously, debuginfo types are annotated to IR builtin preserve_struct_access_index() and preserve_union_access_index(), but not preserve_array_access_index(). The debug info is useful to identify the root type name which later will be used for type comparison. For user access without explicit type conversions, the previous scheme works as we can ignore intermediate compiler generated type conversions (e.g., from union types to union members) and still generate correct access index string. The issue comes with user explicit type conversions, e.g., converting an array to a structure like below: struct t { int a; char b[40]; }; struct p { int c; int d; }; struct t *var = ...; ... __builtin_preserve_access_index(&(((struct p *)&(var->b[0]))->d)) ... Although BPF backend can derive the type of &(var->b[0]), explicit type annotation make checking more consistent and less error prone. Another benefit is for multiple dimension array handling. For example, struct p { int c; int d; } g[8][9][10]; ... __builtin_preserve_access_index(&g[2][3][4].d) ... It would be possible to calculate the number of "struct p"'s before accessing its member "d" if array debug info is available as it contains each dimension range. This patch enables to annotate IR builtin preserve_array_access_index() with proper debuginfo type. The unit test case and language reference is updated as well. Signed-off-by: Yonghong Song Differential Revision: https://reviews.llvm.org/D65664 llvm-svn: 367724 (cherry picked from commit d0ea05d5eff475a27a5d3bbe4d9fd389935f9cb2) --- clang/lib/CodeGen/CGExpr.cpp | 12 ++++++++--- .../CodeGen/builtin-preserve-access-index-array.c | 18 +++++++++++++++++ clang/test/CodeGen/builtin-preserve-access-index.c | 23 +++++++++++----------- llvm/docs/LangRef.rst | 4 ++++ llvm/include/llvm/IR/IRBuilder.h | 10 +++++++--- llvm/test/CodeGen/BPF/CORE/intrinsic-array.ll | 2 +- 6 files changed, 51 insertions(+), 18 deletions(-) create mode 100644 clang/test/CodeGen/builtin-preserve-access-index-array.c diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index b6c2567..21c4103 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -3405,6 +3405,7 @@ static Address emitArraySubscriptGEP(CodeGenFunction &CGF, Address addr, ArrayRef indices, QualType eltType, bool inbounds, bool signedIndices, SourceLocation loc, + QualType *arrayType = nullptr, const llvm::Twine &name = "arrayidx") { // All the indices except that last must be zero. #ifndef NDEBUG @@ -3433,9 +3434,12 @@ static Address emitArraySubscriptGEP(CodeGenFunction &CGF, Address addr, } else { // Remember the original array subscript for bpf target unsigned idx = LastIndex->getZExtValue(); + llvm::DIType *DbgInfo = nullptr; + if (arrayType) + DbgInfo = CGF.getDebugInfo()->getOrCreateStandaloneType(*arrayType, loc); eltPtr = CGF.Builder.CreatePreserveArrayAccessIndex(addr.getPointer(), indices.size() - 1, - idx); + idx, DbgInfo); } return Address(eltPtr, eltAlign); @@ -3572,19 +3576,21 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E, auto *Idx = EmitIdxAfterBase(/*Promote*/true); // Propagate the alignment from the array itself to the result. + QualType arrayType = Array->getType(); Addr = emitArraySubscriptGEP( *this, ArrayLV.getAddress(), {CGM.getSize(CharUnits::Zero()), Idx}, E->getType(), !getLangOpts().isSignedOverflowDefined(), SignedIndices, - E->getExprLoc()); + E->getExprLoc(), &arrayType); EltBaseInfo = ArrayLV.getBaseInfo(); EltTBAAInfo = CGM.getTBAAInfoForSubobject(ArrayLV, E->getType()); } else { // The base must be a pointer; emit it with an estimate of its alignment. Addr = EmitPointerWithAlignment(E->getBase(), &EltBaseInfo, &EltTBAAInfo); auto *Idx = EmitIdxAfterBase(/*Promote*/true); + QualType ptrType = E->getBase()->getType(); Addr = emitArraySubscriptGEP(*this, Addr, Idx, E->getType(), !getLangOpts().isSignedOverflowDefined(), - SignedIndices, E->getExprLoc()); + SignedIndices, E->getExprLoc(), &ptrType); } LValue LV = MakeAddrLValue(Addr, E->getType(), EltBaseInfo, EltTBAAInfo); diff --git a/clang/test/CodeGen/builtin-preserve-access-index-array.c b/clang/test/CodeGen/builtin-preserve-access-index-array.c new file mode 100644 index 0000000..a449b28 --- /dev/null +++ b/clang/test/CodeGen/builtin-preserve-access-index-array.c @@ -0,0 +1,18 @@ +// RUN: %clang -target x86_64 -emit-llvm -S -g %s -o - | FileCheck %s + +#define _(x) (__builtin_preserve_access_index(x)) + +struct s1 { + char a; + int b[4]; +}; + +const void *unit1(struct s1 *arg) { + return _(&arg->b[2]); +} +// CHECK: define dso_local i8* @unit1 +// CHECK: call [4 x i32]* @llvm.preserve.struct.access.index.p0a4i32.p0s_struct.s1s(%struct.s1* %{{[0-9a-z]+}}, i32 1, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S1:[0-9]+]] +// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0a4i32([4 x i32]* %{{[0-9a-z]+}}, i32 1, i32 2), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[ARRAY:[0-9]+]] +// +// CHECK: ![[ARRAY]] = !DICompositeType(tag: DW_TAG_array_type +// CHECK: ![[STRUCT_S1]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "s1" diff --git a/clang/test/CodeGen/builtin-preserve-access-index.c b/clang/test/CodeGen/builtin-preserve-access-index.c index 954a3b8..1084416 100644 --- a/clang/test/CodeGen/builtin-preserve-access-index.c +++ b/clang/test/CodeGen/builtin-preserve-access-index.c @@ -31,16 +31,16 @@ const void *unit4(const int *arg) { } // CHECK: define dso_local i8* @unit4 // CHECK-NOT: getelementptr -// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0i32(i32* %{{[0-9a-z]+}}, i32 0, i32 1) +// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0i32(i32* %{{[0-9a-z]+}}, i32 0, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[POINTER:[0-9]+]] const void *unit5(const int *arg[5]) { return _(&arg[1][2]); } // CHECK: define dso_local i8* @unit5 // CHECK-NOT: getelementptr -// CHECK: call i32** @llvm.preserve.array.access.index.p0p0i32.p0p0i32(i32** %{{[0-9a-z]+}}, i32 0, i32 1) +// CHECK: call i32** @llvm.preserve.array.access.index.p0p0i32.p0p0i32(i32** %{{[0-9a-z]+}}, i32 0, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index !{{[0-9]+}} // CHECK-NOT: getelementptr -// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0i32(i32* %{{[0-9a-z]+}}, i32 0, i32 2) +// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0i32(i32* %{{[0-9a-z]+}}, i32 0, i32 2), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[POINTER:[0-9]+]] struct s1 { char a; @@ -141,7 +141,7 @@ const void *unit13(struct s4 *arg) { // CHECK: define dso_local i8* @unit13 // CHECK: call %union.u* @llvm.preserve.struct.access.index.p0s_union.us.p0s_struct.s4s(%struct.s4* %{{[0-9a-z]+}}, i32 1, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S4:[0-9]+]] // CHECK: call %union.u* @llvm.preserve.union.access.index.p0s_union.us.p0s_union.us(%union.u* %{{[0-9a-z]+}}, i32 0), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[UNION_I_U:[0-9]+]] -// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0a4i32([4 x i32]* %{{[0-9a-z]+}}, i32 1, i32 2) +// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0a4i32([4 x i32]* %{{[0-9a-z]+}}, i32 1, i32 2), !dbg !{{[0-9]+}}, !llvm.preserve.access.index !{{[0-9]+}} const void *unit14(union u3 *arg) { return _(&arg->c.b[2]); @@ -149,13 +149,13 @@ const void *unit14(union u3 *arg) { // CHECK: define dso_local i8* @unit14 // CHECK: call %union.u3* @llvm.preserve.union.access.index.p0s_union.u3s.p0s_union.u3s(%union.u3* %{{[0-9a-z]+}}, i32 0), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[UNION_U3:[0-9]+]] // CHECK: call [4 x i32]* @llvm.preserve.struct.access.index.p0a4i32.p0s_struct.ss(%struct.s* %{{[0-9a-z]+}}, i32 0, i32 0), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_I_S:[0-9]+]] -// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0a4i32([4 x i32]* %{{[0-9a-z]+}}, i32 1, i32 2) +// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0a4i32([4 x i32]* %{{[0-9a-z]+}}, i32 1, i32 2), !dbg !{{[0-9]+}}, !llvm.preserve.access.index !{{[0-9]+}} const void *unit15(struct s4 *arg) { return _(&arg[2].c.a); } // CHECK: define dso_local i8* @unit15 -// CHECK: call %struct.s4* @llvm.preserve.array.access.index.p0s_struct.s4s.p0s_struct.s4s(%struct.s4* %{{[0-9a-z]+}}, i32 0, i32 2) +// CHECK: call %struct.s4* @llvm.preserve.array.access.index.p0s_struct.s4s.p0s_struct.s4s(%struct.s4* %{{[0-9a-z]+}}, i32 0, i32 2), !dbg !{{[0-9]+}}, !llvm.preserve.access.index !{{[0-9]+}} // CHECK: call %union.u* @llvm.preserve.struct.access.index.p0s_union.us.p0s_struct.s4s(%struct.s4* %{{[0-9a-z]+}}, i32 1, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S4]] // CHECK: call %union.u* @llvm.preserve.union.access.index.p0s_union.us.p0s_union.us(%union.u* %{{[0-9a-z]+}}, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[UNION_I_U]] @@ -163,15 +163,16 @@ const void *unit16(union u3 *arg) { return _(&arg[2].a); } // CHECK: define dso_local i8* @unit16 -// CHECK: call %union.u3* @llvm.preserve.array.access.index.p0s_union.u3s.p0s_union.u3s(%union.u3* %{{[0-9a-z]+}}, i32 0, i32 2) +// CHECK: call %union.u3* @llvm.preserve.array.access.index.p0s_union.u3s.p0s_union.u3s(%union.u3* %{{[0-9a-z]+}}, i32 0, i32 2), !dbg !{{[0-9]+}}, !llvm.preserve.access.index !{{[0-9]+}} // CHECK: call %union.u3* @llvm.preserve.union.access.index.p0s_union.u3s.p0s_union.u3s(%union.u3* %{{[0-9a-z]+}}, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[UNION_U3]] +// CHECK: ![[POINTER]] = !DIDerivedType(tag: DW_TAG_pointer_type +// CHECK: ![[STRUCT_S4]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "s4" +// CHECK: ![[UNION_I_U]] = distinct !DICompositeType(tag: DW_TAG_union_type, name: "u" +// CHECK: ![[UNION_U3]] = distinct !DICompositeType(tag: DW_TAG_union_type, name: "u3" +// CHECK: ![[STRUCT_I_S]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "s" // CHECK: ![[STRUCT_S1]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "s1" // CHECK: ![[STRUCT_S2]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "s2" // CHECK: ![[STRUCT_S3]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "s3" // CHECK: ![[UNION_U1]] = distinct !DICompositeType(tag: DW_TAG_union_type, name: "u1" // CHECK: ![[UNION_U2]] = distinct !DICompositeType(tag: DW_TAG_union_type, name: "u2" -// CHECK: ![[STRUCT_S4]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "s4" -// CHECK: ![[UNION_I_U]] = distinct !DICompositeType(tag: DW_TAG_union_type, name: "u" -// CHECK: ![[UNION_U3]] = distinct !DICompositeType(tag: DW_TAG_union_type, name: "u3" -// CHECK: ![[STRUCT_I_S]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "s" -- 1.8.3.1