From a9fa85841102e81daaa23650d89b120fe9dacedc Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Thu, 1 Jul 2010 06:20:47 +0000 Subject: [PATCH] fix rdar://8147692 - yet another crash due to my abi work. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@107387 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGCall.cpp | 23 ++++++++++++++++------- lib/CodeGen/CodeGenTypes.cpp | 27 +++++++++++++++++++-------- lib/CodeGen/CodeGenTypes.h | 6 ++++++ test/CodeGen/decl.c | 15 +++++++++++++++ 4 files changed, 56 insertions(+), 15 deletions(-) diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index 29104424ac..c0c2a47207 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -251,18 +251,27 @@ const CGFunctionInfo &CodeGenTypes::getFunctionInfo(CanQualType ResTy, // If this is being called from the guts of the ConvertType loop, make sure // to call ConvertTypeRecursive so we don't get into issues with cyclic // pointer type structures. - const llvm::Type *ArgType; - if (IsRecursive) - ArgType = ConvertTypeRecursive(*I); - else - ArgType = ConvertType(*I); - PreferredArgTypes.push_back(ArgType); + PreferredArgTypes.push_back(ConvertTypeRecursive(*I)); } - + // Compute ABI information. getABIInfo().computeInfo(*FI, getContext(), TheModule.getContext(), PreferredArgTypes.data(), PreferredArgTypes.size()); + // If this is a top-level call and ConvertTypeRecursive hit unresolved pointer + // types, resolve them now. These pointers may point to this function, which + // we *just* filled in the FunctionInfo for. + if (!IsRecursive && !PointersToResolve.empty()) { + // Use PATypeHolder's so that our preferred types don't dangle under + // refinement. + llvm::SmallVector Handles(PreferredArgTypes.begin(), + PreferredArgTypes.end()); + HandleLateResolvedPointers(); + PreferredArgTypes.clear(); + PreferredArgTypes.append(Handles.begin(), Handles.end()); + } + + return *FI; } diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp index 7876e5aefc..d469b906fc 100644 --- a/lib/CodeGen/CodeGenTypes.cpp +++ b/lib/CodeGen/CodeGenTypes.cpp @@ -42,14 +42,11 @@ CodeGenTypes::~CodeGenTypes() { delete &*I++; } -/// ConvertType - Convert the specified type to its LLVM form. -const llvm::Type *CodeGenTypes::ConvertType(QualType T, bool IsRecursive) { - const llvm::Type *RawResult = ConvertTypeRecursive(T); - - if (IsRecursive || PointersToResolve.empty()) - return RawResult; - - llvm::PATypeHolder Result = RawResult; +/// HandleLateResolvedPointers - For top-level ConvertType calls, this handles +/// pointers that are referenced but have not been converted yet. This is used +/// to handle cyclic structures properly. +void CodeGenTypes::HandleLateResolvedPointers() { + assert(!PointersToResolve.empty() && "No pointers to resolve!"); // Any pointers that were converted deferred evaluation of their pointee type, // creating an opaque type instead. This is in order to avoid problems with @@ -64,7 +61,21 @@ const llvm::Type *CodeGenTypes::ConvertType(QualType T, bool IsRecursive) { const llvm::Type *NT = ConvertTypeForMemRecursive(P.first); P.second->refineAbstractTypeTo(NT); } +} + +/// ConvertType - Convert the specified type to its LLVM form. +const llvm::Type *CodeGenTypes::ConvertType(QualType T, bool IsRecursive) { + const llvm::Type *Result = ConvertTypeRecursive(T); + + // If this is a top-level call to ConvertType and sub-conversions caused + // pointers to get lazily built as opaque types, resolve the pointers, which + // might cause Result to be merged away. + if (!IsRecursive && !PointersToResolve.empty()) { + llvm::PATypeHolder ResultHandle = Result; + HandleLateResolvedPointers(); + Result = ResultHandle; + } return Result; } diff --git a/lib/CodeGen/CodeGenTypes.h b/lib/CodeGen/CodeGenTypes.h index bf55fc5369..c7f48e6c9d 100644 --- a/lib/CodeGen/CodeGenTypes.h +++ b/lib/CodeGen/CodeGenTypes.h @@ -94,6 +94,12 @@ private: /// is available only for ConvertType(). CovertType() is preferred /// interface to convert type T into a llvm::Type. const llvm::Type *ConvertNewType(QualType T); + + /// HandleLateResolvedPointers - For top-level ConvertType calls, this handles + /// pointers that are referenced but have not been converted yet. This is + /// used to handle cyclic structures properly. + void HandleLateResolvedPointers(); + public: CodeGenTypes(ASTContext &Ctx, llvm::Module &M, const llvm::TargetData &TD, const ABIInfo &Info); diff --git a/test/CodeGen/decl.c b/test/CodeGen/decl.c index dcf120fd88..7a9971ee18 100644 --- a/test/CodeGen/decl.c +++ b/test/CodeGen/decl.c @@ -102,3 +102,18 @@ void init_error(void) { global_dc->x = cp_diagnostic_starter; } + + +// rdar://8147692 - ABI crash in recursive struct-through-function-pointer. +typedef struct { + int x5a; +} x5; + +typedef struct x2 *x0; +typedef long (*x1)(x0 x0a, x5 x6); +struct x2 { + x1 x4; +}; +long x3(x0 x0a, x5 a) { + return x0a->x4(x0a, a); +} -- 2.40.0