summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen/CGDecl.cpp
diff options
context:
space:
mode:
authorReid Kleckner <reid@kleckner.net>2014-02-01 00:04:45 +0000
committerReid Kleckner <reid@kleckner.net>2014-02-01 00:04:45 +0000
commit314ef7bafda9f507540f3294359f20ba7bcf7a8d (patch)
tree12c1045bd69401d2014764c56bb55a6a717913f3 /clang/lib/CodeGen/CGDecl.cpp
parentf5b76518c9c1afd2e08a59c11f3de8fb25540b58 (diff)
downloadbcm5719-llvm-314ef7bafda9f507540f3294359f20ba7bcf7a8d.tar.gz
bcm5719-llvm-314ef7bafda9f507540f3294359f20ba7bcf7a8d.zip
[ms-cxxabi] Use inalloca on win32 when passing non-trivial C++ objects
When a non-trivial parameter is present, clang now gathers up all the parameters that lack inreg and puts them into a packed struct. MSVC always aligns each parameter to 4 bytes and no more, so this is a pretty simple struct to lay out. On win64, non-trivial records are passed indirectly. Prior to this change, clang was incorrectly using byval on win64. I'm able to self-host a working clang with this change and additional LLVM patches. Reviewers: rsmith Differential Revision: http://llvm-reviews.chandlerc.com/D2636 llvm-svn: 200597
Diffstat (limited to 'clang/lib/CodeGen/CGDecl.cpp')
-rw-r--r--clang/lib/CodeGen/CGDecl.cpp46
1 files changed, 26 insertions, 20 deletions
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index e87be5f4148..cb48e84aacb 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -944,7 +944,7 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
// Push a cleanup block and restore the stack there.
// FIXME: in general circumstances, this should be an EH cleanup.
- EHStack.pushCleanup<CallStackRestore>(NormalCleanup, Stack);
+ pushStackRestore(NormalCleanup, Stack);
}
llvm::Value *elementCount;
@@ -1344,6 +1344,10 @@ void CodeGenFunction::pushDestroy(CleanupKind cleanupKind, llvm::Value *addr,
destroyer, useEHCleanupForArray);
}
+void CodeGenFunction::pushStackRestore(CleanupKind Kind, llvm::Value *SPMem) {
+ EHStack.pushCleanup<CallStackRestore>(Kind, SPMem);
+}
+
void CodeGenFunction::pushLifetimeExtendedDestroy(
CleanupKind cleanupKind, llvm::Value *addr, QualType type,
Destroyer *destroyer, bool useEHCleanupForArray) {
@@ -1603,7 +1607,7 @@ namespace {
/// Emit an alloca (or GlobalValue depending on target)
/// for the specified parameter and set up LocalDeclMap.
void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg,
- unsigned ArgNo) {
+ bool ArgIsPointer, unsigned ArgNo) {
// FIXME: Why isn't ImplicitParamDecl a ParmVarDecl?
assert((isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D)) &&
"Invalid argument to EmitParmDecl");
@@ -1641,30 +1645,32 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg,
}
llvm::Value *DeclPtr;
- bool HasNonScalarEvalKind = !CodeGenFunction::hasScalarEvaluationKind(Ty);
- // If this is an aggregate or variable sized value, reuse the input pointer.
- if (HasNonScalarEvalKind || !Ty->isConstantSizeType()) {
+ bool DoStore = false;
+ bool IsScalar = hasScalarEvaluationKind(Ty);
+ CharUnits Align = getContext().getDeclAlign(&D);
+ // If we already have a pointer to the argument, reuse the input pointer.
+ if (ArgIsPointer) {
+ assert(isa<llvm::PointerType>(Arg->getType()));
DeclPtr = Arg;
// Push a destructor cleanup for this parameter if the ABI requires it.
- if (HasNonScalarEvalKind &&
+ if (!IsScalar &&
getTarget().getCXXABI().areArgsDestroyedLeftToRightInCallee()) {
- if (const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl()) {
- if (RD->hasNonTrivialDestructor())
- pushDestroy(QualType::DK_cxx_destructor, DeclPtr, Ty);
- }
+ const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl();
+ if (RD && RD->hasNonTrivialDestructor())
+ pushDestroy(QualType::DK_cxx_destructor, DeclPtr, Ty);
}
} else {
// Otherwise, create a temporary to hold the value.
llvm::AllocaInst *Alloc = CreateTempAlloca(ConvertTypeForMem(Ty),
D.getName() + ".addr");
- CharUnits Align = getContext().getDeclAlign(&D);
Alloc->setAlignment(Align.getQuantity());
DeclPtr = Alloc;
+ DoStore = true;
+ }
- bool doStore = true;
-
+ LValue lv = MakeAddrLValue(DeclPtr, Ty, Align);
+ if (IsScalar) {
Qualifiers qs = Ty.getQualifiers();
- LValue lv = MakeAddrLValue(DeclPtr, Ty, Align);
if (Qualifiers::ObjCLifetime lt = qs.getObjCLifetime()) {
// We honor __attribute__((ns_consumed)) for types with lifetime.
// For __strong, it's handled by just skipping the initial retain;
@@ -1693,7 +1699,7 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg,
llvm::Value *Null = CGM.EmitNullConstant(D.getType());
EmitStoreOfScalar(Null, lv, /* isInitialization */ true);
EmitARCStoreStrongCall(lv.getAddress(), Arg, true);
- doStore = false;
+ DoStore = false;
}
else
// Don't use objc_retainBlock for block pointers, because we
@@ -1712,19 +1718,19 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg,
if (lt == Qualifiers::OCL_Weak) {
EmitARCInitWeak(DeclPtr, Arg);
- doStore = false; // The weak init is a store, no need to do two.
+ DoStore = false; // The weak init is a store, no need to do two.
}
}
// Enter the cleanup scope.
EmitAutoVarWithLifetime(*this, D, DeclPtr, lt);
}
-
- // Store the initial value into the alloca.
- if (doStore)
- EmitStoreOfScalar(Arg, lv, /* isInitialization */ true);
}
+ // Store the initial value into the alloca.
+ if (DoStore)
+ EmitStoreOfScalar(Arg, lv, /* isInitialization */ true);
+
llvm::Value *&DMEntry = LocalDeclMap[&D];
assert(DMEntry == 0 && "Decl already exists in localdeclmap!");
DMEntry = DeclPtr;
OpenPOWER on IntegriCloud