diff options
Diffstat (limited to 'lib/CodeGen/CGExprConstant.cpp')
-rw-r--r-- | lib/CodeGen/CGExprConstant.cpp | 159 |
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!"); |