diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index bd920a2e3f2dd..a7e571ec465c2 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -1424,7 +1424,8 @@ void CodeGenFunction::CreateCoercedStore(llvm::Value *Src, Address Dst, SrcSize == CGM.getDataLayout().getTypeAllocSize(Dst.getElementType())) { // If the value is supposed to be a pointer, convert it before storing it. Src = CoerceIntOrPtrToIntOrPtr(Src, Dst.getElementType(), *this); - Builder.CreateStore(Src, Dst, DstIsVolatile); + auto *I = Builder.CreateStore(Src, Dst, DstIsVolatile); + addInstToCurrentSourceAtom(I, Src); } else if (llvm::StructType *STy = dyn_cast(Src->getType())) { // Prefer scalar stores to first-class aggregate stores. @@ -1432,16 +1433,21 @@ void CodeGenFunction::CreateCoercedStore(llvm::Value *Src, Address Dst, for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { Address EltPtr = Builder.CreateStructGEP(Dst, i); llvm::Value *Elt = Builder.CreateExtractValue(Src, i); - Builder.CreateStore(Elt, EltPtr, DstIsVolatile); + auto *I = Builder.CreateStore(Elt, EltPtr, DstIsVolatile); + addInstToCurrentSourceAtom(I, Elt); } } else { - Builder.CreateStore(Src, Dst.withElementType(SrcTy), DstIsVolatile); + auto *I = + Builder.CreateStore(Src, Dst.withElementType(SrcTy), DstIsVolatile); + addInstToCurrentSourceAtom(I, Src); } } else if (SrcTy->isIntegerTy()) { // If the source is a simple integer, coerce it directly. llvm::Type *DstIntTy = Builder.getIntNTy(DstSize.getFixedValue() * 8); Src = CoerceIntOrPtrToIntOrPtr(Src, DstIntTy, *this); - Builder.CreateStore(Src, Dst.withElementType(DstIntTy), DstIsVolatile); + auto *I = + Builder.CreateStore(Src, Dst.withElementType(DstIntTy), DstIsVolatile); + addInstToCurrentSourceAtom(I, Src); } else { // Otherwise do coercion through memory. This is stupid, but // simple. @@ -1455,10 +1461,11 @@ void CodeGenFunction::CreateCoercedStore(llvm::Value *Src, Address Dst, RawAddress Tmp = CreateTempAllocaForCoercion(*this, SrcTy, Dst.getAlignment()); Builder.CreateStore(Src, Tmp); - Builder.CreateMemCpy(Dst.emitRawPointer(*this), - Dst.getAlignment().getAsAlign(), Tmp.getPointer(), - Tmp.getAlignment().getAsAlign(), - Builder.CreateTypeSize(IntPtrTy, DstSize)); + auto *I = Builder.CreateMemCpy( + Dst.emitRawPointer(*this), Dst.getAlignment().getAsAlign(), + Tmp.getPointer(), Tmp.getAlignment().getAsAlign(), + Builder.CreateTypeSize(IntPtrTy, DstSize)); + addInstToCurrentSourceAtom(I, Src); } } diff --git a/clang/test/DebugInfo/KeyInstructions/coerced-packed.c b/clang/test/DebugInfo/KeyInstructions/coerced-packed.c new file mode 100644 index 0000000000000..90ec8420b0d8c --- /dev/null +++ b/clang/test/DebugInfo/KeyInstructions/coerced-packed.c @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -gkey-instructions -gno-column-info -x c++ %s -debug-info-kind=line-tables-only -emit-llvm -o - -triple arm64-apple-ios11 \ +// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank + +// RUN: %clang_cc1 -gkey-instructions -gno-column-info -x c %s -debug-info-kind=line-tables-only -emit-llvm -o - -triple arm64-apple-ios11 \ +// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank + +typedef struct { + char a; + int x; +} __attribute((packed)) S; + +S getS(); +void f() { +// CHECK: [[call:%.*]] = call i40{{.*}}getS{{.*}}, !dbg [[G1R2:!.*]] +// CHECK: store i40 [[call]], ptr %s, align 1, !dbg [[G1R1:!.*]] + S s = getS(); +} + +// CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2) +// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1) diff --git a/clang/test/DebugInfo/KeyInstructions/coerced-ptr.c b/clang/test/DebugInfo/KeyInstructions/coerced-ptr.c new file mode 100644 index 0000000000000..0002e9051220b --- /dev/null +++ b/clang/test/DebugInfo/KeyInstructions/coerced-ptr.c @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -gkey-instructions -gno-column-info -x c++ %s -debug-info-kind=line-tables-only -emit-llvm -o - -triple x86_64-windows-msvc \ +// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank + +// RUN: %clang_cc1 -gkey-instructions -gno-column-info -x c %s -debug-info-kind=line-tables-only -emit-llvm -o - -triple x86_64-windows-msvc \ +// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank + +typedef struct { int *p; } Ptr; +Ptr getPtr(); +void f() { +// CHECK: %call = call i64{{.*}}, !dbg [[G1R3:!.*]] +// CHECK: [[gep:%.*]] = getelementptr inbounds nuw %struct.Ptr, ptr %p, i32 0, i32 0 +// CHECK: [[i2p:%.*]] = inttoptr i64 %call to ptr, !dbg [[G1R2:!.*]] +// CHECK: store ptr [[i2p]], ptr [[gep]], align 8, !dbg [[G1R1:!.*]] + Ptr p = getPtr(); +} + +// CHECK: [[G1R3]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 3) +// CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2) +// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1) diff --git a/clang/test/DebugInfo/KeyInstructions/coerced-through-memory.c b/clang/test/DebugInfo/KeyInstructions/coerced-through-memory.c new file mode 100644 index 0000000000000..98361aa9806ef --- /dev/null +++ b/clang/test/DebugInfo/KeyInstructions/coerced-through-memory.c @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -gkey-instructions -gno-column-info -x c++ %s -debug-info-kind=line-tables-only -emit-llvm -o - -triple aarch64-windows-msvc \ +// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank + +// RUN: %clang_cc1 -gkey-instructions -gno-column-info -x c %s -debug-info-kind=line-tables-only -emit-llvm -o - -triple aarch64-windows-msvc \ +// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank + +typedef struct { + short a; + int b; + short c; +} S; + +S getS(void); + +void f() { +// CHECK: %call = call [2 x i64] {{.*}}getS{{.*}}(), !dbg [[G1R2:!.*]] +//// Note: The store to the tmp alloca isn't part of the atom. +// CHECK: store [2 x i64] %call, ptr %tmp.coerce, align 8 +// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %s, ptr align 8 %tmp.coerce, i64 12, i1 false), !dbg [[G1R1:!.*]] + S s = getS(); +} + +// CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2) +// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1) diff --git a/clang/test/DebugInfo/KeyInstructions/coerced.c b/clang/test/DebugInfo/KeyInstructions/coerced.c new file mode 100644 index 0000000000000..b5a254fb641c9 --- /dev/null +++ b/clang/test/DebugInfo/KeyInstructions/coerced.c @@ -0,0 +1,36 @@ +// RUN: %clang_cc1 -gkey-instructions -gno-column-info -x c++ %s -debug-info-kind=line-tables-only -emit-llvm -o - -triple x86_64-unknown-linux \ +// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank --check-prefixes=CHECK,CHECK-CXX + +// RUN: %clang_cc1 -gkey-instructions -gno-column-info -x c %s -debug-info-kind=line-tables-only -emit-llvm -o - -triple x86_64-unknown-linux \ +// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank --check-prefixes=CHECK,CHECK-C + +typedef struct { + void* a; + void* b; +} Struct; +Struct get(); + +void test() { +// CHECK: %1 = extractvalue { ptr, ptr } %call, 0, !dbg [[G1R2:!.*]] +// CHECK: store ptr %1, ptr {{.*}}, !dbg [[G1R1:!.*]] +// CHECK: %3 = extractvalue { ptr, ptr } %call, 1, !dbg [[G1R2]] +// CHECK: store ptr %3, ptr {{.*}}, !dbg [[G1R1:!.*]] + Struct s = get(); +} + +typedef struct { int i; } Int; +Int getInt(void); + +// CHECK-C: @test2 +// CHECK-CXX: @_Z5test2v +void test2() { +// CHECK: %call = call i32 @{{(_Z6)?}}getInt{{v?}}(), !dbg [[T2_G1R2:!.*]] +// CHECK: [[gep:%.*]] = getelementptr inbounds nuw %struct.Int, ptr %i, i32 0, i32 0 +// CHECK: store i32 %call, ptr [[gep]]{{.*}}, !dbg [[T2_G1R1:!.*]] + Int i = getInt(); +} + +// CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2) +// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1) +// CHECK: [[T2_G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2) +// CHECK: [[T2_G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)