[cfe-commits] r134853 - in /cfe/trunk: lib/CodeGen/CGCall.cpp lib/CodeGen/CGVTables.cpp lib/CodeGen/CodeGenTypes.cpp lib/CodeGen/CodeGenTypes.h lib/CodeGen/ItaniumCXXABI.cpp test/CodeGen/init.c
Chris Lattner
sabre at nondot.org
Sat Jul 9 17:18:59 PDT 2011
Author: lattner
Date: Sat Jul 9 19:18:59 2011
New Revision: 134853
URL: http://llvm.org/viewvc/llvm-project?rev=134853&view=rev
Log:
Rename CGT::VerifyFuncTypeComplete to isFuncTypeConvertible since
it is a predicate, not an action. Change the return type to be a bool,
not the incomplete member. Enhace it to detect the recursive compilation
case, allowing us to compile Eli's testcase on llvmdev:
struct T {
struct T (*p)(void);
} t;
into:
%struct.T = type { {}* }
@t = common global %struct.T zeroinitializer, align 8
Modified:
cfe/trunk/lib/CodeGen/CGCall.cpp
cfe/trunk/lib/CodeGen/CGVTables.cpp
cfe/trunk/lib/CodeGen/CodeGenTypes.cpp
cfe/trunk/lib/CodeGen/CodeGenTypes.h
cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
cfe/trunk/test/CodeGen/init.c
Modified: cfe/trunk/lib/CodeGen/CGCall.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCall.cpp?rev=134853&r1=134852&r2=134853&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCall.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCall.cpp Sat Jul 9 19:18:59 2011
@@ -704,16 +704,15 @@
const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
- if (!VerifyFuncTypeComplete(FPT)) {
- const CGFunctionInfo *Info;
- if (isa<CXXDestructorDecl>(MD))
- Info = &getFunctionInfo(cast<CXXDestructorDecl>(MD), GD.getDtorType());
- else
- Info = &getFunctionInfo(MD);
- return GetFunctionType(*Info, FPT->isVariadic());
- }
-
- return llvm::StructType::get(getLLVMContext());
+ if (!isFuncTypeConvertible(FPT))
+ return llvm::StructType::get(getLLVMContext());
+
+ const CGFunctionInfo *Info;
+ if (isa<CXXDestructorDecl>(MD))
+ Info = &getFunctionInfo(cast<CXXDestructorDecl>(MD), GD.getDtorType());
+ else
+ Info = &getFunctionInfo(MD);
+ return GetFunctionType(*Info, FPT->isVariadic());
}
void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
Modified: cfe/trunk/lib/CodeGen/CGVTables.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGVTables.cpp?rev=134853&r1=134852&r2=134853&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGVTables.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGVTables.cpp Sat Jul 9 19:18:59 2011
@@ -2937,7 +2937,8 @@
// We can't emit thunks for member functions with incomplete types.
const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
- if (CGM.getTypes().VerifyFuncTypeComplete(MD->getType().getTypePtr()))
+ if (!CGM.getTypes().isFuncTypeConvertible(
+ cast<FunctionType>(MD->getType().getTypePtr())))
return;
EmitThunk(GD, Thunk, /*UseAvailableExternallyLinkage=*/true);
Modified: cfe/trunk/lib/CodeGen/CodeGenTypes.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenTypes.cpp?rev=134853&r1=134852&r2=134853&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenTypes.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenTypes.cpp Sat Jul 9 19:18:59 2011
@@ -93,19 +93,55 @@
}
-// Code to verify a given function type is complete, i.e. the return type
-// and all of the argument types are complete.
-const TagType *CodeGenTypes::VerifyFuncTypeComplete(const Type* T) {
- const FunctionType *FT = cast<FunctionType>(T);
- if (const TagType* TT = FT->getResultType()->getAs<TagType>())
- if (!TT->getDecl()->isDefinition())
- return TT;
- if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(T))
+/// isFuncTypeArgumentConvertible - Return true if the specified type in a
+/// function argument or result position can be converted to an IR type at this
+/// point. This boils down to being whether it is complete, as well as whether
+/// we've temporarily deferred expanding the type because we're in a recursive
+/// context.
+bool CodeGenTypes::isFuncTypeArgumentConvertible(QualType Ty){
+ // If this isn't a tagged type, we can convert it!
+ const TagType *TT = Ty->getAs<TagType>();
+ if (TT == 0) return true;
+
+ // If it's a tagged type, but is a forward decl, we can't convert it.
+ if (!TT->getDecl()->isDefinition())
+ return false;
+
+ // If we're not under a pointer under a struct, then we can convert it if
+ // needed.
+ if (RecursionState != RS_StructPointer)
+ return true;
+
+ // If this is an enum, then it is safe to convert.
+ const RecordType *RT = dyn_cast<RecordType>(TT);
+ if (RT == 0) return true;
+
+ // Otherwise, we have to be careful. If it is a struct that we're in the
+ // process of expanding, then we can't convert the function type. That's ok
+ // though because we must be in a pointer context under the struct, so we can
+ // just convert it to a dummy type.
+ //
+ // We decide this by checking whether ConvertRecordDeclType returns us an
+ // opaque type for a struct that we know is defined.
+ return !ConvertRecordDeclType(RT->getDecl())->isOpaque();
+}
+
+
+/// Code to verify a given function type is complete, i.e. the return type
+/// and all of the argument types are complete. Also check to see if we are in
+/// a RS_StructPointer context, and if so whether any struct types have been
+/// pended. If so, we don't want to ask the ABI lowering code to handle a type
+/// that cannot be converted to an IR type.
+bool CodeGenTypes::isFuncTypeConvertible(const FunctionType *FT) {
+ if (!isFuncTypeArgumentConvertible(FT->getResultType()))
+ return false;
+
+ if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(FT))
for (unsigned i = 0, e = FPT->getNumArgs(); i != e; i++)
- if (const TagType *TT = FPT->getArgType(i)->getAs<TagType>())
- if (!TT->getDecl()->isDefinition())
- return TT;
- return 0;
+ if (!isFuncTypeArgumentConvertible(FPT->getArgType(i)))
+ return false;
+
+ return true;
}
/// UpdateCompletedType - When we find the full definition for a TagDecl,
@@ -296,7 +332,7 @@
// First, check whether we can build the full function type. If the
// function type depends on an incomplete type (e.g. a struct or enum), we
// cannot lower the function type.
- if (VerifyFuncTypeComplete(Ty)) {
+ if (!isFuncTypeConvertible(cast<FunctionType>(Ty))) {
// This function's type depends on an incomplete tag type.
// Return a placeholder type.
ResultType = llvm::StructType::get(getLLVMContext());
Modified: cfe/trunk/lib/CodeGen/CodeGenTypes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenTypes.h?rev=134853&r1=134852&r2=134853&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenTypes.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenTypes.h Sat Jul 9 19:18:59 2011
@@ -137,11 +137,12 @@
llvm::FunctionType *GetFunctionType(GlobalDecl GD);
- /// VerifyFuncTypeComplete - Utility to check whether a function type can
+ /// isFuncTypeConvertible - Utility to check whether a function type can
/// be converted to an LLVM type (i.e. doesn't depend on an incomplete tag
/// type).
- static const TagType *VerifyFuncTypeComplete(const Type* T);
-
+ bool isFuncTypeConvertible(const FunctionType *FT);
+ bool isFuncTypeArgumentConvertible(QualType Ty);
+
/// GetFunctionTypeForVTable - Get the LLVM function type for use in a vtable,
/// given a CXXMethodDecl. If the method to has an incomplete return type,
/// and/or incomplete argument types, this will return the opaque type.
Modified: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=134853&r1=134852&r2=134853&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp Sat Jul 9 19:18:59 2011
@@ -537,7 +537,7 @@
const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>();
const llvm::Type *Ty;
// Check whether the function has a computable LLVM signature.
- if (!CodeGenTypes::VerifyFuncTypeComplete(FPT)) {
+ if (Types.isFuncTypeConvertible(FPT)) {
// The function has a computable LLVM signature; use the correct type.
Ty = Types.GetFunctionType(Types.getFunctionInfo(MD),
FPT->isVariadic());
Modified: cfe/trunk/test/CodeGen/init.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/init.c?rev=134853&r1=134852&r2=134853&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/init.c (original)
+++ cfe/trunk/test/CodeGen/init.c Sat Jul 9 19:18:59 2011
@@ -115,3 +115,11 @@
// CHECK: store i32 4
// CHECK: ret void
}
+
+
+// Verify that we can convert a recursive struct with a memory that returns
+// an instance of the struct we're converting.
+struct test12 {
+ struct test12 (*p)(void);
+} test12g;
+
More information about the cfe-commits
mailing list