x86-64 ABI: If a type is a C++ record with either a non-trivial destructor or a non-trivial copy constructor, it should be passed in a pointer. Daniel, plz review.

llvm-svn: 82050
This commit is contained in:
Anders Carlsson 2009-09-16 15:53:40 +00:00
parent a0f1088134
commit 20759ad54c
5 changed files with 56 additions and 9 deletions

View File

@ -388,7 +388,7 @@
1ADF47AE0F782C3200E48A8A /* SemaTemplateInstantiateDecl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = SemaTemplateInstantiateDecl.cpp; path = lib/Sema/SemaTemplateInstantiateDecl.cpp; sourceTree = "<group>"; tabWidth = 2; };
1AE4EE3B103B89CA00888A23 /* TreeTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = TreeTransform.h; path = lib/Sema/TreeTransform.h; sourceTree = "<group>"; tabWidth = 2; };
1AE4EE3D103B89ED00888A23 /* StmtProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = StmtProfile.cpp; path = lib/AST/StmtProfile.cpp; sourceTree = "<group>"; tabWidth = 2; };
1AE4EE3F103B8A0A00888A23 /* TargetABIInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TargetABIInfo.cpp; path = lib/CodeGen/TargetABIInfo.cpp; sourceTree = "<group>"; };
1AE4EE3F103B8A0A00888A23 /* TargetABIInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = TargetABIInfo.cpp; path = lib/CodeGen/TargetABIInfo.cpp; sourceTree = "<group>"; tabWidth = 2; };
1AFEF4050F8A6B2300476F2B /* clang-cc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = "clang-cc.cpp"; path = "tools/clang-cc/clang-cc.cpp"; sourceTree = "<group>"; tabWidth = 2; };
1AFF8AE11012BFC900D248DA /* CGRecordLayoutBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGRecordLayoutBuilder.cpp; path = lib/CodeGen/CGRecordLayoutBuilder.cpp; sourceTree = "<group>"; tabWidth = 2; };
1AFF8AE21012BFC900D248DA /* CGRecordLayoutBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = CGRecordLayoutBuilder.h; path = lib/CodeGen/CGRecordLayoutBuilder.h; sourceTree = "<group>"; tabWidth = 2; };

View File

@ -72,11 +72,12 @@ namespace clang {
Kind TheKind;
const llvm::Type *TypeData;
unsigned UIntData;
bool BoolData;
ABIArgInfo(Kind K, const llvm::Type *TD=0,
unsigned UI=0) : TheKind(K),
TypeData(TD),
UIntData(UI) {}
unsigned UI=0, bool B = false)
: TheKind(K), TypeData(TD), UIntData(UI), BoolData(B) {}
public:
ABIArgInfo() : TheKind(Direct), TypeData(0), UIntData(0) {}
@ -92,8 +93,8 @@ namespace clang {
static ABIArgInfo getCoerce(const llvm::Type *T) {
return ABIArgInfo(Coerce, T);
}
static ABIArgInfo getIndirect(unsigned Alignment) {
return ABIArgInfo(Indirect, 0, Alignment);
static ABIArgInfo getIndirect(unsigned Alignment, bool ByVal = true) {
return ABIArgInfo(Indirect, 0, Alignment, ByVal);
}
static ABIArgInfo getExpand() {
return ABIArgInfo(Expand);
@ -113,12 +114,17 @@ namespace clang {
return TypeData;
}
// ByVal accessors
// Indirect accessors
unsigned getIndirectAlign() const {
assert(TheKind == Indirect && "Invalid kind!");
return UIntData;
}
bool getIndirectByVal() const {
assert(TheKind == Indirect && "Invalid kind!");
return BoolData;
}
void dump() const;
};

View File

@ -492,7 +492,9 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
break;
case ABIArgInfo::Indirect:
Attributes |= llvm::Attribute::ByVal;
if (AI.getIndirectByVal())
Attributes |= llvm::Attribute::ByVal;
Attributes |=
llvm::Attribute::constructAlignmentFromInt(AI.getIndirectAlign());
// byval disables readnone and readonly.

View File

@ -86,6 +86,27 @@ static bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays) {
return true;
}
/// hasNonTrivialDestructorOrCopyConstructor - Determine if a type has either
/// a non-trivial destructor or a non-trivial copy constructor.
static bool hasNonTrivialDestructorOrCopyConstructor(const RecordType *RT) {
const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
if (!RD)
return false;
return !RD->hasTrivialDestructor() || !RD->hasTrivialCopyConstructor();
}
/// isRecordWithNonTrivialDestructorOrCopyConstructor - Determine if a type is
/// a record type with either a non-trivial destructor or a non-trivial copy
/// constructor.
static bool isRecordWithNonTrivialDestructorOrCopyConstructor(QualType T) {
const RecordType *RT = T->getAs<RecordType>();
if (!RT)
return false;
return hasNonTrivialDestructorOrCopyConstructor(RT);
}
/// isSingleElementStruct - Determine if a structure is a "single
/// element struct", i.e. it has exactly one non-empty field or
/// exactly one field which is itself a single element
@ -717,6 +738,12 @@ void X86_64ABIInfo::classify(QualType Ty,
if (Size > 128)
return;
// AMD64-ABI 3.2.3p2: Rule 2. If a C++ object has either a non-trivial
// copy constructor or a non-trivial destructor, it is passed by invisible
// reference.
if (hasNonTrivialDestructorOrCopyConstructor(RT))
return;
const RecordDecl *RD = RT->getDecl();
// Assume variable sized types are passed in memory.
@ -830,8 +857,10 @@ ABIArgInfo X86_64ABIInfo::getIndirectResult(QualType Ty,
return (Ty->isPromotableIntegerType() ?
ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
bool ByVal = !isRecordWithNonTrivialDestructorOrCopyConstructor(Ty);
// FIXME: Set alignment correctly.
return ABIArgInfo::getIndirect(0);
return ABIArgInfo::getIndirect(0, ByVal);
}
ABIArgInfo X86_64ABIInfo::classifyReturnType(QualType RetTy,

View File

@ -0,0 +1,10 @@
// RUN: clang-cc -triple x86_64-unknown-unknown -emit-llvm -o %t %s &&
struct A { ~A(); };
// RUN: grep 'define void @_Z2f11A(.struct.A\* .a)' %t &&
void f1(A a) { }
// RUN: grep 'define void @_Z2f2v(.struct.A\* noalias sret .agg.result)' %t &&
A f2() { return A(); }
// RUN: true