summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorReid Kleckner <rnk@google.com>2016-09-07 18:21:30 +0000
committerReid Kleckner <rnk@google.com>2016-09-07 18:21:30 +0000
commite5a321b5e8777c63d5ebfb896137dcf16ead4f15 (patch)
tree8afc36f18681b53c33863d5c714745eda67f26f5
parent6c45f9233c0cb47855bf2f144079277656d5a30e (diff)
downloadbcm5719-llvm-e5a321b5e8777c63d5ebfb896137dcf16ead4f15.tar.gz
bcm5719-llvm-e5a321b5e8777c63d5ebfb896137dcf16ead4f15.zip
[MS] Fix prologue this adjustment when 'this' is passed indirectly
Move the logic for doing this from the ABI argument lowering into EmitParmDecl, which runs for all parameters. Our codegen is slightly suboptimal in this case, as we may leave behind a dead store after optimization, but it's 32-bit inalloca, and this fixes the bug in a robust way. Fixes PR30293 llvm-svn: 280836
-rw-r--r--clang/lib/CodeGen/CGCall.cpp7
-rw-r--r--clang/lib/CodeGen/CGDecl.cpp19
-rw-r--r--clang/test/CodeGenCXX/constructor-destructor-return-this.cpp2
-rw-r--r--clang/test/CodeGenCXX/microsoft-abi-structors.cpp2
-rw-r--r--clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp2
-rw-r--r--clang/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-this-adjustment.cpp23
6 files changed, 45 insertions, 10 deletions
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index f3eaef369a6..454cc5e3e77 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -2309,13 +2309,6 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
if (isPromoted)
V = emitArgumentDemotion(*this, Arg, V);
- if (const CXXMethodDecl *MD =
- dyn_cast_or_null<CXXMethodDecl>(CurCodeDecl)) {
- if (MD->isVirtual() && Arg == CXXABIThisDecl)
- V = CGM.getCXXABI().
- adjustThisParameterInVirtualFunctionPrologue(*this, CurGD, V);
- }
-
// Because of merging of function types from multiple decls it is
// possible for the type of an argument to not match the corresponding
// type in the function type. Since we are codegening the callee
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index 037b1351c0f..5b4017cad37 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -13,6 +13,7 @@
#include "CodeGenFunction.h"
#include "CGBlocks.h"
+#include "CGCXXABI.h"
#include "CGCleanup.h"
#include "CGDebugInfo.h"
#include "CGOpenCLRuntime.h"
@@ -1769,6 +1770,24 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, ParamValue Arg,
setBlockContextParameter(IPD, ArgNo, Arg.getDirectValue());
return;
}
+
+ // Apply any prologue 'this' adjustments required by the ABI. Be careful to
+ // handle the case where 'this' is passed indirectly as part of an inalloca
+ // struct.
+ if (const CXXMethodDecl *MD =
+ dyn_cast_or_null<CXXMethodDecl>(CurCodeDecl)) {
+ if (MD->isVirtual() && IPD == CXXABIThisDecl) {
+ llvm::Value *This = Arg.isIndirect()
+ ? Builder.CreateLoad(Arg.getIndirectAddress())
+ : Arg.getDirectValue();
+ This = CGM.getCXXABI().adjustThisParameterInVirtualFunctionPrologue(
+ *this, CurGD, This);
+ if (Arg.isIndirect())
+ Builder.CreateStore(This, Arg.getIndirectAddress());
+ else
+ Arg = ParamValue::forDirect(This);
+ }
+ }
}
Address DeclPtr = Address::invalid();
diff --git a/clang/test/CodeGenCXX/constructor-destructor-return-this.cpp b/clang/test/CodeGenCXX/constructor-destructor-return-this.cpp
index 9d47d1706bb..164fda3c1c3 100644
--- a/clang/test/CodeGenCXX/constructor-destructor-return-this.cpp
+++ b/clang/test/CodeGenCXX/constructor-destructor-return-this.cpp
@@ -111,7 +111,7 @@ D::~D() { }
// CHECKIOS5-LABEL: define %class.D* @_ZN1DD1Ev(%class.D* %this)
// CHECKMS-LABEL: define x86_thiscallcc %class.D* @"\01??0D@@QAE@XZ"(%class.D* returned %this, i32 %is_most_derived)
-// CHECKMS-LABEL: define x86_thiscallcc void @"\01??1D@@UAE@XZ"(%class.D*)
+// CHECKMS-LABEL: define x86_thiscallcc void @"\01??1D@@UAE@XZ"(%class.D* %this)
class E {
public:
diff --git a/clang/test/CodeGenCXX/microsoft-abi-structors.cpp b/clang/test/CodeGenCXX/microsoft-abi-structors.cpp
index a576f0c3d7e..cd453b68e3b 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-structors.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-structors.cpp
@@ -196,7 +196,7 @@ struct E : virtual C { int e; };
struct F : D, E { ~F(); int f; };
F::~F() {
-// CHECK-LABEL: define x86_thiscallcc void @"\01??1F@test2@@UAE@XZ"(%"struct.test2::F"*)
+// CHECK-LABEL: define x86_thiscallcc void @"\01??1F@test2@@UAE@XZ"(%"struct.test2::F"*{{[^,]*}})
// Do an adjustment from C vbase subobject to F as though F was the
// complete type.
// CHECK: getelementptr inbounds i8, i8* %{{.*}}, i32 -20
diff --git a/clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp b/clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp
index 480ae8cfbbe..eaf1e3d6c3e 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp
@@ -283,7 +283,7 @@ struct D : virtual Z, B, C {
} d;
D::~D() {
- // CHECK-LABEL: define x86_thiscallcc void @"\01??1D@diamond@@UAE@XZ"(%"struct.diamond::D"*)
+ // CHECK-LABEL: define x86_thiscallcc void @"\01??1D@diamond@@UAE@XZ"(%"struct.diamond::D"*{{.*}})
// CHECK: %[[ARG_i8:.*]] = bitcast %"struct.diamond::D"* %{{.*}} to i8*
// CHECK: %[[THIS_i8:.*]] = getelementptr inbounds i8, i8* %[[ARG_i8]], i32 -24
// CHECK: %[[THIS:.*]] = bitcast i8* %[[THIS_i8]] to %"struct.diamond::D"*
diff --git a/clang/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-this-adjustment.cpp b/clang/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-this-adjustment.cpp
index aaee39c51db..b97c432f5e0 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-this-adjustment.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-this-adjustment.cpp
@@ -177,3 +177,26 @@ void fop(C &c) {
}
}
+
+namespace pr30293 {
+struct NonTrivial {
+ ~NonTrivial();
+ int x;
+};
+struct A { virtual void f(); };
+struct B { virtual void __cdecl g(NonTrivial); };
+struct C final : A, B {
+ void f() override;
+ void __cdecl g(NonTrivial) override;
+};
+C *whatsthis;
+void C::f() { g(NonTrivial()); }
+void C::g(NonTrivial o) {
+ whatsthis = this;
+}
+
+// BITCODE-LABEL: define void @"\01?g@C@pr30293@@UAAXUNonTrivial@2@@Z"(<{ i8*, %"struct.pr30293::NonTrivial" }>* inalloca)
+// BITCODE: %[[this1:[^ ]*]] = load i8*, i8** %[[thisaddr:[^ ]*]], align 4
+// BITCODE-NEXT: %[[this2:[^ ]*]] = getelementptr inbounds i8, i8* %[[this1]], i32 -4
+// BITCODE-NEXT: store i8* %[[this2]], i8** %[[thisaddr]], align 4
+}
OpenPOWER on IntegriCloud