keep track of whether being in a RS_StructPointer state

caused us to skip layout out a function accurately.  If
so, flush the type cache for both the function and struct
case to ensure that any pointers to the functions get
recomputed.  This is overconservative, but with this patch
clang can build itself again.

llvm-svn: 134863
This commit is contained in:
Chris Lattner 2011-07-10 05:39:13 +00:00
parent 13ee4f4834
commit 117b724b59
5 changed files with 20 additions and 9 deletions

View File

@ -32,6 +32,7 @@ CodeGenTypes::CodeGenTypes(ASTContext &Ctx, llvm::Module& M,
: Context(Ctx), Target(Ctx.Target), TheModule(M), TheTargetData(TD),
TheABIInfo(Info), TheCXXABI(CXXABI), CodeGenOpts(CGO) {
RecursionState = RS_Normal;
SkippedLayout = false;
}
CodeGenTypes::~CodeGenTypes() {
@ -345,6 +346,8 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
// This function's type depends on an incomplete tag type.
// Return a placeholder type.
ResultType = llvm::StructType::get(getLLVMContext());
SkippedLayout |= RecursionState == RS_StructPointer;
break;
}
@ -373,6 +376,9 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
// Restore our recursion state.
RecursionState = SavedRecursionState;
if (SkippedLayout)
TypeCache.clear();
if (RecursionState == RS_Normal)
while (!DeferredRecords.empty())
@ -487,7 +493,8 @@ llvm::StructType *CodeGenTypes::ConvertRecordDeclType(const RecordDecl *RD) {
// If this struct blocked a FunctionType conversion, then recompute whatever
// was derived from that.
// FIXME: This is hugely overconservative.
TypeCache.clear();
if (SkippedLayout)
TypeCache.clear();
// Restore our recursion state. If we're done converting the outer-most

View File

@ -86,7 +86,11 @@ class CodeGenTypes {
RS_Struct, // Recursively inside a struct conversion.
RS_StructPointer // Recursively inside a pointer in a struct.
} RecursionState;
/// SkippedLayout - True if we didn't layout a function bit due to a
/// RS_StructPointer RecursionState.
bool SkippedLayout;
llvm::SmallVector<const RecordDecl *, 8> DeferredRecords;
struct RecursionStatePointerRAII {

View File

@ -86,7 +86,7 @@ namespace test3 {
// CHECK-NEXT: [[UNION:%.*]] = getelementptr inbounds {{.*}} [[THIS]], i32 0, i32 0
// CHECK-NEXT: [[STRUCT:%.*]] = bitcast {{.*}}* [[UNION]] to
// CHECK-NEXT: [[CALLBACK:%.*]] = getelementptr inbounds {{.*}} [[STRUCT]], i32 0, i32 0
// CHECK-NEXT: store {{.*}}* null, {{.*}}** [[CALLBACK]]
// CHECK: store {{.*}}* null, {{.*}}** [[CALLBACK]]
// CHECK-NEXT: [[UNION:%.*]] = getelementptr inbounds {{.*}} [[THIS]], i32 0, i32 0
// CHECK-NEXT: [[STRUCT:%.*]] = bitcast {{.*}}* [[UNION]] to
// CHECK-NEXT: [[CVALUE:%.*]] = getelementptr inbounds {{.*}} [[STRUCT]], i32 0, i32 1

View File

@ -34,7 +34,7 @@ void test0(NSArray *array) {
// CHECK-LP64-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]])
// CHECK-LP64-NEXT: store i8* [[T2]], i8** [[T0]]
// CHECK-LP64-NEXT: [[T1:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]]
// CHECK-LP64-NEXT: call void @use_block({{.*}}* [[T1]])
// CHECK-LP64: call void @use_block(
// CHECK-LP64-NEXT: [[T1:%.*]] = load i8** [[T0]]
// CHECK-LP64-NEXT: call void @objc_release(i8* [[T1]])
@ -67,6 +67,6 @@ void test1(NSArray *array) {
// CHECK-LP64-NEXT: [[T1:%.*]] = call i8* @objc_loadWeak(i8** [[X]])
// CHECK-LP64-NEXT: call i8* @objc_initWeak(i8** [[T0]], i8* [[T1]])
// CHECK-LP64-NEXT: [[T1:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to
// CHECK-LP64-NEXT: call void @use_block({{.*}} [[T1]])
// CHECK-LP64: call void @use_block
// CHECK-LP64-NEXT: call void @objc_destroyWeak(i8** [[T0]])
// CHECK-LP64-NEXT: call void @objc_destroyWeak(i8** [[X]])

View File

@ -1216,7 +1216,7 @@ void test39(void) {
// CHECK: define void @test39()
// CHECK: [[VAR:%.*]] = alloca i8*
// CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
// CHECK-NEXT: [[T0:%.*]] = call i8* @test39_source()
// CHECK: [[T0:%.*]] = call i8* @test39_source()
// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
// CHECK-NEXT: store i8* [[T1]], i8** [[VAR]],
// CHECK-NEXT: call void @objc_release(i8* [[T1]])
@ -1226,7 +1226,7 @@ void test39(void) {
// CHECK-NEXT: [[T0:%.*]] = load i8** [[VAR]]
// CHECK-NEXT: store i8* [[T0]], i8** [[CAPTURE]]
// CHECK-NEXT: [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to
// CHECK-NEXT: call void @test39_helper({{.*}} [[T0]])
// CHECK: call void @test39_helper
// CHECK-NEXT: ret void
}
@ -1330,7 +1330,7 @@ void test41(void) {
// CHECK: [[SELF:%.*]] = alloca [[TEST42:%.*]]*,
// CHECK-NEXT: alloca i8*
// CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
// CHECK-NEXT: store
// CHECK: store
// CHECK-NEXT: store
// CHECK: [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
// CHECK-NEXT: [[T1:%.*]] = load [[TEST42]]** [[SELF]],
@ -1339,7 +1339,7 @@ void test41(void) {
// CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to [[TEST42]]*
// CHECK-NEXT: store [[TEST42]]* [[T4]], [[TEST42]]** [[T0]]
// CHECK-NEXT: bitcast [[BLOCK_T]]* [[BLOCK]] to
// CHECK-NEXT: call void @test42_helper(
// CHECK: call void @test42_helper(
// CHECK-NEXT: [[T1:%.*]] = load [[TEST42]]** [[T0]]
// CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST42]]* [[T1]] to i8*
// CHECK-NEXT: call void @objc_release(i8* [[T2]])