Index: llvm/trunk/docs/LangRef.rst =================================================================== --- llvm/trunk/docs/LangRef.rst +++ llvm/trunk/docs/LangRef.rst @@ -17304,3 +17304,106 @@ """"""""" Lowers to a call to `objc_storeWeak `_. + +Preserving Debug Information Intrinsics +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +These intrinsics are used to carry certain debuginfo together with +IR-level operations. For example, it may be desirable to +know the structure/union name and the original user-level field +indices. Such information got lost in IR GetElementPtr instruction +since the IR types are different from debugInfo types and unions +are converted to structs in IR. + +'``llvm.preserve.array.access.index``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" +:: + + declare + @llvm.preserve.array.access.index.p0s_union.anons.p0a10s_union.anons( base, + i32 dim, + i32 index) + +Overview: +""""""""" + +The '``llvm.preserve.array.access.index``' intrinsic returns the getelementptr address +based on array base ``base``, array dimension ``dim`` and the last access index ``index`` +into the array. + +Arguments: +"""""""""" + +The ``base`` is the array base address. The ``dim`` is the array dimension. +The ``base`` is a pointer if ``dim`` equals 0. +The ``index`` is the last access index into the array or pointer. + +Semantics: +"""""""""" + +The '``llvm.preserve.array.access.index``' intrinsic produces the same result +as a getelementptr with base ``base`` and access operands ``{dim's 0's, index}``. + +'``llvm.preserve.union.access.index``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" +:: + + declare + @llvm.preserve.union.access.index.p0s_union.anons.p0s_union.anons( base, + i32 di_index) + +Overview: +""""""""" + +The '``llvm.preserve.union.access.index``' intrinsic carries the debuginfo field index +``di_index`` and returns the ``base`` address. +The ``llvm.preserve.access.index`` type of metadata is attached to this call instruction +to provide union debuginfo type. + +Arguments: +"""""""""" + +The ``base`` is the union base address. The ``di_index`` is the field index in debuginfo. + +Semantics: +"""""""""" + +The '``llvm.preserve.union.access.index``' intrinsic returns the ``base`` address. + +'``llvm.preserve.struct.access.index``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" +:: + + declare + @llvm.preserve.struct.access.index.p0i8.p0s_struct.anon.0s( base, + i32 gep_index, + i32 di_index) + +Overview: +""""""""" + +The '``llvm.preserve.struct.access.index``' intrinsic returns the getelementptr address +based on struct base ``base`` and IR struct member index ``gep_index``. +The ``llvm.preserve.access.index`` type of metadata is attached to this call instruction +to provide struct debuginfo type. + +Arguments: +"""""""""" + +The ``base`` is the structure base address. The ``gep_index`` is the struct member index +based on IR structures. The ``di_index`` is the struct member index based on debuginfo. + +Semantics: +"""""""""" + +The '``llvm.preserve.struct.access.index``' intrinsic produces the same result +as a getelementptr with base ``base`` and access operands ``{0, gep_index}``. Index: llvm/trunk/include/llvm/IR/IRBuilder.h =================================================================== --- llvm/trunk/include/llvm/IR/IRBuilder.h +++ llvm/trunk/include/llvm/IR/IRBuilder.h @@ -2453,6 +2453,74 @@ return V; } + Value *CreatePreserveArrayAccessIndex(Value *Base, unsigned Dimension, + unsigned LastIndex) { + assert(isa(Base->getType()) && + "Invalid Base ptr type for preserve.array.access.index."); + auto *BaseType = Base->getType(); + + Value *LastIndexV = getInt32(LastIndex); + Constant *Zero = ConstantInt::get(Type::getInt32Ty(Context), 0); + SmallVector IdxList; + for (unsigned I = 0; I < Dimension; ++I) + IdxList.push_back(Zero); + IdxList.push_back(LastIndexV); + + Type *ResultType = + GetElementPtrInst::getGEPReturnType(Base, IdxList); + + Module *M = BB->getParent()->getParent(); + Function *FnPreserveArrayAccessIndex = Intrinsic::getDeclaration( + M, Intrinsic::preserve_array_access_index, {ResultType, BaseType}); + + Value *DimV = getInt32(Dimension); + CallInst *Fn = + CreateCall(FnPreserveArrayAccessIndex, {Base, DimV, LastIndexV}); + + return Fn; + } + + Value *CreatePreserveUnionAccessIndex(Value *Base, unsigned FieldIndex, + MDNode *DbgInfo) { + assert(isa(Base->getType()) && + "Invalid Base ptr type for preserve.union.access.index."); + auto *BaseType = Base->getType(); + + Module *M = BB->getParent()->getParent(); + Function *FnPreserveUnionAccessIndex = Intrinsic::getDeclaration( + M, Intrinsic::preserve_union_access_index, {BaseType, BaseType}); + + Value *DIIndex = getInt32(FieldIndex); + CallInst *Fn = + CreateCall(FnPreserveUnionAccessIndex, {Base, DIIndex}); + Fn->setMetadata(LLVMContext::MD_preserve_access_index, DbgInfo); + + return Fn; + } + + Value *CreatePreserveStructAccessIndex(Value *Base, unsigned Index, + unsigned FieldIndex, MDNode *DbgInfo) { + assert(isa(Base->getType()) && + "Invalid Base ptr type for preserve.struct.access.index."); + auto *BaseType = Base->getType(); + + Value *GEPIndex = getInt32(Index); + Constant *Zero = ConstantInt::get(Type::getInt32Ty(Context), 0); + Type *ResultType = + GetElementPtrInst::getGEPReturnType(Base, {Zero, GEPIndex}); + + Module *M = BB->getParent()->getParent(); + Function *FnPreserveStructAccessIndex = Intrinsic::getDeclaration( + M, Intrinsic::preserve_struct_access_index, {ResultType, BaseType}); + + Value *DIIndex = getInt32(FieldIndex); + CallInst *Fn = CreateCall(FnPreserveStructAccessIndex, + {Base, GEPIndex, DIIndex}); + Fn->setMetadata(LLVMContext::MD_preserve_access_index, DbgInfo); + + return Fn; + } + private: /// Helper function that creates an assume intrinsic call that /// represents an alignment assumption on the provided Ptr, Mask, Type Index: llvm/trunk/include/llvm/IR/Intrinsics.td =================================================================== --- llvm/trunk/include/llvm/IR/Intrinsics.td +++ llvm/trunk/include/llvm/IR/Intrinsics.td @@ -1040,7 +1040,6 @@ // Intrinsic to detect whether its argument is a constant. def int_is_constant : Intrinsic<[llvm_i1_ty], [llvm_any_ty], [IntrNoMem], "llvm.is.constant">; - //===-------------------------- Masked Intrinsics -------------------------===// // def int_masked_store : Intrinsic<[], [llvm_anyvector_ty, @@ -1214,6 +1213,22 @@ def int_ssa_copy : Intrinsic<[llvm_any_ty], [LLVMMatchType<0>], [IntrNoMem, Returned<0>]>; + +//===------- Intrinsics that are used to preserve debug information -------===// + +def int_preserve_array_access_index : Intrinsic<[llvm_anyptr_ty], + [llvm_anyptr_ty, llvm_i32_ty, + llvm_i32_ty], + [IntrNoMem, ImmArg<1>, ImmArg<2>]>; +def int_preserve_union_access_index : Intrinsic<[llvm_anyptr_ty], + [llvm_anyptr_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<1>]>; +def int_preserve_struct_access_index : Intrinsic<[llvm_anyptr_ty], + [llvm_anyptr_ty, llvm_i32_ty, + llvm_i32_ty], + [IntrNoMem, ImmArg<1>, + ImmArg<2>]>; + //===----------------------------------------------------------------------===// // Target-specific intrinsics //===----------------------------------------------------------------------===// Index: llvm/trunk/include/llvm/IR/LLVMContext.h =================================================================== --- llvm/trunk/include/llvm/IR/LLVMContext.h +++ llvm/trunk/include/llvm/IR/LLVMContext.h @@ -99,6 +99,7 @@ MD_irr_loop = 24, // "irr_loop" MD_access_group = 25, // "llvm.access.group" MD_callback = 26, // "callback" + MD_preserve_access_index = 27, // "llvm.preserve.*.access.index" }; /// Known operand bundle tag IDs, which always have the same value. All Index: llvm/trunk/lib/IR/LLVMContext.cpp =================================================================== --- llvm/trunk/lib/IR/LLVMContext.cpp +++ llvm/trunk/lib/IR/LLVMContext.cpp @@ -63,6 +63,7 @@ {MD_irr_loop, "irr_loop"}, {MD_access_group, "llvm.access.group"}, {MD_callback, "callback"}, + {MD_preserve_access_index, "llvm.preserve.access.index"}, }; for (auto &MDKind : MDKinds) {