aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGExprConstant.cpp
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2011-02-15 06:40:56 +0000
committerJohn McCall <rjmccall@apple.com>2011-02-15 06:40:56 +0000
commit9b7da1c46d6d2849f9cb51328d7fcddf2c417672 (patch)
tree586f035ba023d43ad7c063ca7c2ac642e9bef469 /lib/CodeGen/CGExprConstant.cpp
parentfe59b7472c06b36efb74fbb50bbdf464fa30c0d8 (diff)
Perform zero-initialization of virtual base classes when emitting
a zero constant for a complete class. rdar://problem/8424975 To make this happen, track the field indexes for virtual bases in the complete object. I'm curious whether we might be better off making CGRecordLayoutBuilder *much* more reliant on ASTRecordLayout; we're currently duplicating an awful lot of the ABI layout logic. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@125555 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGExprConstant.cpp')
-rw-r--r--lib/CodeGen/CGExprConstant.cpp159
1 files changed, 97 insertions, 62 deletions
diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp
index d4d9c92838..1f222a2bd1 100644
--- a/lib/CodeGen/CGExprConstant.cpp
+++ b/lib/CodeGen/CGExprConstant.cpp
@@ -1036,87 +1036,122 @@ FillInNullDataMemberPointers(CodeGenModule &CGM, QualType T,
}
}
-static llvm::Constant *EmitNullConstant(CodeGenModule &CGM,
- const CXXRecordDecl *RD) {
- QualType T = CGM.getContext().getTagDeclType(RD);
-
- const llvm::StructType *STy =
- cast<llvm::StructType>(CGM.getTypes().ConvertTypeForMem(T));
- unsigned NumElements = STy->getNumElements();
- std::vector<llvm::Constant *> Elements(NumElements);
+static llvm::Constant *EmitNullConstantForBase(CodeGenModule &CGM,
+ const llvm::Type *baseType,
+ const CXXRecordDecl *base);
- const CGRecordLayout &Layout = CGM.getTypes().getCGRecordLayout(RD);
-
- for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
- E = RD->bases_end(); I != E; ++I) {
+static llvm::Constant *EmitNullConstant(CodeGenModule &CGM,
+ const CXXRecordDecl *record,
+ bool asCompleteObject) {
+ const CGRecordLayout &layout = CGM.getTypes().getCGRecordLayout(record);
+ const llvm::StructType *structure =
+ (asCompleteObject ? layout.getLLVMType()
+ : layout.getBaseSubobjectLLVMType());
+
+ unsigned numElements = structure->getNumElements();
+ std::vector<llvm::Constant *> elements(numElements);
+
+ // Fill in all the bases.
+ for (CXXRecordDecl::base_class_const_iterator
+ I = record->bases_begin(), E = record->bases_end(); I != E; ++I) {
if (I->isVirtual()) {
- // Ignore virtual bases.
+ // Ignore virtual bases; if we're laying out for a complete
+ // object, we'll lay these out later.
continue;
}
- const CXXRecordDecl *BaseDecl =
- cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+ const CXXRecordDecl *base =
+ cast<CXXRecordDecl>(I->getType()->castAs<RecordType>()->getDecl());
// Ignore empty bases.
- if (BaseDecl->isEmpty())
+ if (base->isEmpty())
continue;
- // Ignore bases that don't have any pointer to data members.
- if (CGM.getTypes().isZeroInitializable(BaseDecl))
- continue;
-
- unsigned BaseFieldNo = Layout.getNonVirtualBaseLLVMFieldNo(BaseDecl);
- const llvm::Type *BaseTy = STy->getElementType(BaseFieldNo);
-
- if (isa<llvm::StructType>(BaseTy)) {
- // We can just emit the base as a null constant.
- Elements[BaseFieldNo] = EmitNullConstant(CGM, BaseDecl);
- continue;
- }
-
- // Some bases are represented as arrays of i8 if the size of the
- // base is smaller than its corresponding LLVM type.
- // Figure out how many elements this base array has.
- const llvm::ArrayType *BaseArrayTy = cast<llvm::ArrayType>(BaseTy);
- unsigned NumBaseElements = BaseArrayTy->getNumElements();
-
- // Fill in null data member pointers.
- std::vector<llvm::Constant *> BaseElements(NumBaseElements);
- FillInNullDataMemberPointers(CGM, I->getType(), BaseElements, 0);
-
- // Now go through all other elements and zero them out.
- if (NumBaseElements) {
- const llvm::Type* Int8Ty = llvm::Type::getInt8Ty(CGM.getLLVMContext());
- llvm::Constant *Zero = llvm::Constant::getNullValue(Int8Ty);
- for (unsigned I = 0; I != NumBaseElements; ++I) {
- if (!BaseElements[I])
- BaseElements[I] = Zero;
- }
- }
-
- Elements[BaseFieldNo] = llvm::ConstantArray::get(BaseArrayTy, BaseElements);
+ unsigned fieldIndex = layout.getNonVirtualBaseLLVMFieldNo(base);
+ const llvm::Type *baseType = structure->getElementType(fieldIndex);
+ elements[fieldIndex] = EmitNullConstantForBase(CGM, baseType, base);
}
- // Visit all fields.
- for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
- I != E; ++I) {
- const FieldDecl *FD = *I;
+ // Fill in all the fields.
+ for (RecordDecl::field_iterator I = record->field_begin(),
+ E = record->field_end(); I != E; ++I) {
+ const FieldDecl *field = *I;
// Ignore bit fields.
- if (FD->isBitField())
+ if (field->isBitField())
continue;
- unsigned FieldNo = Layout.getLLVMFieldNo(FD);
- Elements[FieldNo] = CGM.EmitNullConstant(FD->getType());
+ unsigned fieldIndex = layout.getLLVMFieldNo(field);
+ elements[fieldIndex] = CGM.EmitNullConstant(field->getType());
+ }
+
+ // Fill in the virtual bases, if we're working with the complete object.
+ if (asCompleteObject) {
+ for (CXXRecordDecl::base_class_const_iterator
+ I = record->vbases_begin(), E = record->vbases_end(); I != E; ++I) {
+ const CXXRecordDecl *base =
+ cast<CXXRecordDecl>(I->getType()->castAs<RecordType>()->getDecl());
+
+ // Ignore empty bases.
+ if (base->isEmpty())
+ continue;
+
+ unsigned fieldIndex = layout.getVirtualBaseIndex(base);
+
+ // We might have already laid this field out.
+ if (elements[fieldIndex]) continue;
+
+ const llvm::Type *baseType = structure->getElementType(fieldIndex);
+ elements[fieldIndex] = EmitNullConstantForBase(CGM, baseType, base);
+ }
}
// Now go through all other fields and zero them out.
- for (unsigned i = 0; i != NumElements; ++i) {
- if (!Elements[i])
- Elements[i] = llvm::Constant::getNullValue(STy->getElementType(i));
+ for (unsigned i = 0; i != numElements; ++i) {
+ if (!elements[i])
+ elements[i] = llvm::Constant::getNullValue(structure->getElementType(i));
}
- return llvm::ConstantStruct::get(STy, Elements);
+ return llvm::ConstantStruct::get(structure, elements);
+}
+
+/// Emit the null constant for a base subobject.
+static llvm::Constant *EmitNullConstantForBase(CodeGenModule &CGM,
+ const llvm::Type *baseType,
+ const CXXRecordDecl *base) {
+ const CGRecordLayout &baseLayout = CGM.getTypes().getCGRecordLayout(base);
+
+ // Just zero out bases that don't have any pointer to data members.
+ if (baseLayout.isZeroInitializableAsBase())
+ return llvm::Constant::getNullValue(baseType);
+
+ // If the base type is a struct, we can just use its null constant.
+ if (isa<llvm::StructType>(baseType)) {
+ return EmitNullConstant(CGM, base, /*complete*/ false);
+ }
+
+ // Otherwise, some bases are represented as arrays of i8 if the size
+ // of the base is smaller than its corresponding LLVM type. Figure
+ // out how many elements this base array has.
+ const llvm::ArrayType *baseArrayType = cast<llvm::ArrayType>(baseType);
+ unsigned numBaseElements = baseArrayType->getNumElements();
+
+ // Fill in null data member pointers.
+ std::vector<llvm::Constant *> baseElements(numBaseElements);
+ FillInNullDataMemberPointers(CGM, CGM.getContext().getTypeDeclType(base),
+ baseElements, 0);
+
+ // Now go through all other elements and zero them out.
+ if (numBaseElements) {
+ const llvm::Type *i8 = llvm::Type::getInt8Ty(CGM.getLLVMContext());
+ llvm::Constant *i8_zero = llvm::Constant::getNullValue(i8);
+ for (unsigned i = 0; i != numBaseElements; ++i) {
+ if (!baseElements[i])
+ baseElements[i] = i8_zero;
+ }
+ }
+
+ return llvm::ConstantArray::get(baseArrayType, baseElements);
}
llvm::Constant *CodeGenModule::EmitNullConstant(QualType T) {
@@ -1140,7 +1175,7 @@ llvm::Constant *CodeGenModule::EmitNullConstant(QualType T) {
if (const RecordType *RT = T->getAs<RecordType>()) {
const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
- return ::EmitNullConstant(*this, RD);
+ return ::EmitNullConstant(*this, RD, /*complete object*/ true);
}
assert(T->isMemberPointerType() && "Should only see member pointers here!");