[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