Index: docs/LangRef.rst =================================================================== --- docs/LangRef.rst +++ docs/LangRef.rst @@ -16938,3 +16938,109 @@ """"""""" Lowers to a call to `objc_storeWeak `_. + +Preserving Debug Information Intrinsics +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +These intrinsics are used to carry certain debuginfo together with +certain 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, + i8 *inst_name, + i32 subscript) + +Overview: +""""""""" + +The '``llvm.preserve.array.access.index``' intrinsic returns the getelementptr address +based on array base ``base`` and array subscript ``subscript``. + +Arguments: +"""""""""" + +The ``base`` is the array base address. If the intrinsic is eventually lowered to +a getelementptr instruction, the ``inst_name`` can be used for the name of that +instruction. The ``subscript`` is the array subscript. + +Semantics: +"""""""""" + +The '``llvm.preserve.array.access.index``' intrinsic produces the same result +as a getelementptr with base ``base`` and access operands ``{0, subscript}``. + +'``llvm.preserve.union.access.index``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" +:: + + declare + @llvm.preserve.union.access.index.p0s_union.anons.p0s_union.anons( base, + i8 *type_name, + i32 di_index) + +Overview: +""""""""" + +The '``llvm.preserve.union.access.index``' intrinsic returns the ``base`` address, but +carries union type name ``type_name`` and the debuginfo field index ``di_index``. + +Arguments: +"""""""""" + +The ``base`` is the union base address. The ``type_name`` is the union type name, which +could be ``""`` for anonymous union. The ``di_index`` is the field index in debuginfo. + +Semantics: +"""""""""" + +The '``llvm.preserve.union.access.index``' intrinsic does not change the base +pointer address, but carries additional information, ``type_name`` and ``di_index``. + +'``llvm.preserve.struct.access.index``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" +:: + + declare + @llvm.preserve.struct.access.index.p0i8.p0s_struct.anon.0s( base, + i8 *inst_name, + i8 *type_name, + 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``. + +Arguments: +"""""""""" + +The ``base`` is the structure base address. If the intrinsic is eventually lowered to +a getelementptr instruction, the ``inst_name`` can be used for the name of that +instruction. The ``type_name`` is the structure name in debuginfo. +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: include/llvm/IR/IRBuilder.h =================================================================== --- include/llvm/IR/IRBuilder.h +++ include/llvm/IR/IRBuilder.h @@ -2267,6 +2267,71 @@ return V; } + Value *CreatePreserveArrayAccessIndex(Value *Base, const StringRef &Name, + unsigned Index) { + assert(isa(Base->getType()) && + "Invalid Base ptr type for preserve.array.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 *FnPreserveArrayAccessIndex = Intrinsic::getDeclaration( + M, Intrinsic::preserve_array_access_index, {ResultType, BaseType}); + + Value *InstName = CreateGlobalStringPtr(Name); + CallInst *Fn = + CreateCall(FnPreserveArrayAccessIndex, {Base, InstName, GEPIndex}); + + return Fn; + } + + Value *CreatePreserveUnionAccessIndex(Value *Base, const StringRef &TypeName, + unsigned FieldIndex) { + 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 *RecordName = CreateGlobalStringPtr(TypeName); + Value *DIIndex = getInt32(FieldIndex); + CallInst *Fn = + CreateCall(FnPreserveUnionAccessIndex, {Base, RecordName, DIIndex}); + + return Fn; + } + + Value *CreatePreserveStructAccessIndex(Value *Base, const StringRef &Name, + const StringRef &TypeName, + unsigned Index, unsigned FieldIndex) { + 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 *InstName = CreateGlobalStringPtr(Name); + Value *RecordName = CreateGlobalStringPtr(TypeName); + Value *DIIndex = getInt32(FieldIndex); + CallInst *Fn = CreateCall(FnPreserveStructAccessIndex, + {Base, InstName, RecordName, GEPIndex, DIIndex}); + + return Fn; + } + private: /// Helper function that creates an assume intrinsic call that /// represents an alignment assumption on the provided Ptr, Mask, Type Index: include/llvm/IR/Intrinsics.td =================================================================== --- include/llvm/IR/Intrinsics.td +++ include/llvm/IR/Intrinsics.td @@ -1028,7 +1028,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, @@ -1175,6 +1174,24 @@ 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_ptr_ty, + llvm_i32_ty], + [IntrNoMem, ImmArg<2>]>; +def int_preserve_union_access_index : Intrinsic<[llvm_anyptr_ty], + [llvm_anyptr_ty, llvm_ptr_ty, + llvm_i32_ty], + [IntrNoMem, ImmArg<2>]>; +def int_preserve_struct_access_index : Intrinsic<[llvm_anyptr_ty], + [llvm_anyptr_ty, llvm_ptr_ty, + llvm_ptr_ty, llvm_i32_ty, + llvm_i32_ty], + [IntrNoMem, ImmArg<3>, + ImmArg<4>]>; + //===----------------------------------------------------------------------===// // Target-specific intrinsics //===----------------------------------------------------------------------===//