From f2ccdd2700174c717dc55a0f4c3f5a91ae73ff42 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) Also added back Value *CreatePreserveArrayAccessIndex(Value *Base, unsigned Dimension, unsigned LastIndex); To avoid breaking the ABI. --- 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 | 13 ++++++++++-- llvm/test/CodeGen/BPF/CORE/intrinsic-array.ll | 2 +- 6 files changed, 55 insertions(+), 17 deletions(-) create mode 100644 clang/test/CodeGen/builtin-preserve-access-index-array.c diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index 87e8a55..b63e3af 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -17349,6 +17349,10 @@ based on array base ``base``, array dimension ``dim`` and the last access index into the array. The return type ``ret_type`` is a pointer type to the array element. The array ``dim`` and ``index`` are preserved which is more robust than getelementptr instruction which may be subject to compiler transformation. +The ``llvm.preserve.access.index`` type of metadata is attached to this call instruction +to provide array or pointer debuginfo type. +The metadata is a ``DICompositeType`` or ``DIDerivedType`` representing the +debuginfo version of ``type``. Arguments: """""""""" diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h index a74364d..c2fa9a3 100644 --- a/llvm/include/llvm/IR/IRBuilder.h +++ b/llvm/include/llvm/IR/IRBuilder.h @@ -2455,6 +2455,11 @@ public: Value *CreatePreserveArrayAccessIndex(Value *Base, unsigned Dimension, unsigned LastIndex) { + return CreatePreserveArrayAccessIndex(Base, Dimension, LastIndex, nullptr); + } + + Value *CreatePreserveArrayAccessIndex(Value *Base, unsigned Dimension, + unsigned LastIndex, MDNode *DbgInfo) { assert(isa(Base->getType()) && "Invalid Base ptr type for preserve.array.access.index."); auto *BaseType = Base->getType(); @@ -2476,6 +2481,8 @@ public: Value *DimV = getInt32(Dimension); CallInst *Fn = CreateCall(FnPreserveArrayAccessIndex, {Base, DimV, LastIndexV}); + if (DbgInfo) + Fn->setMetadata(LLVMContext::MD_preserve_access_index, DbgInfo); return Fn; } @@ -2493,7 +2500,8 @@ public: Value *DIIndex = getInt32(FieldIndex); CallInst *Fn = CreateCall(FnPreserveUnionAccessIndex, {Base, DIIndex}); - Fn->setMetadata(LLVMContext::MD_preserve_access_index, DbgInfo); + if (DbgInfo) + Fn->setMetadata(LLVMContext::MD_preserve_access_index, DbgInfo); return Fn; } @@ -2516,7 +2524,8 @@ public: Value *DIIndex = getInt32(FieldIndex); CallInst *Fn = CreateCall(FnPreserveStructAccessIndex, {Base, GEPIndex, DIIndex}); - Fn->setMetadata(LLVMContext::MD_preserve_access_index, DbgInfo); + if (DbgInfo) + Fn->setMetadata(LLVMContext::MD_preserve_access_index, DbgInfo); return Fn; } diff --git a/llvm/test/CodeGen/BPF/CORE/intrinsic-array.ll b/llvm/test/CodeGen/BPF/CORE/intrinsic-array.ll index adbcb9f..fe2c196 100644 --- a/llvm/test/CodeGen/BPF/CORE/intrinsic-array.ll +++ b/llvm/test/CodeGen/BPF/CORE/intrinsic-array.ll @@ -14,7 +14,7 @@ define dso_local i32 @test(%struct.s* %arg) local_unnamed_addr #0 !dbg !7 { entry: call void @llvm.dbg.value(metadata %struct.s* %arg, metadata !17, metadata !DIExpression()), !dbg !18 - %0 = tail call %struct.s* @llvm.preserve.array.access.index.p0s_struct.ss.p0s_struct.ss(%struct.s* %arg, i32 0, i32 2), !dbg !19 + %0 = tail call %struct.s* @llvm.preserve.array.access.index.p0s_struct.ss.p0s_struct.ss(%struct.s* %arg, i32 0, i32 2), !dbg !19, !llvm.preserve.access.index !11 %1 = tail call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.ss(%struct.s* %0, i32 1, i32 1), !dbg !19, !llvm.preserve.access.index !12 %2 = bitcast i32* %1 to i8*, !dbg !19 %call = tail call i32 @get_value(i8* %2) #4, !dbg !20 -- 1.8.3.1