@@ -1521,6 +1521,101 @@ ConstantEmitter::~ConstantEmitter() {
15211521 " not finalized after being initialized for non-abstract emission" );
15221522}
15231523
1524+ static mlir::TypedAttr emitNullConstantForBase (CIRGenModule &cgm,
1525+ mlir::Type baseType,
1526+ const CXXRecordDecl *baseDecl);
1527+
1528+ static mlir::TypedAttr emitNullConstant (CIRGenModule &cgm, const RecordDecl *rd,
1529+ bool asCompleteObject) {
1530+ const CIRGenRecordLayout &layout = cgm.getTypes ().getCIRGenRecordLayout (rd);
1531+ mlir::Type ty = (asCompleteObject ? layout.getCIRType ()
1532+ : layout.getBaseSubobjectCIRType ());
1533+ auto recordTy = mlir::cast<cir::RecordType>(ty);
1534+
1535+ unsigned numElements = recordTy.getNumElements ();
1536+ SmallVector<mlir::Attribute> elements (numElements);
1537+
1538+ auto *cxxrd = dyn_cast<CXXRecordDecl>(rd);
1539+ // Fill in all the bases.
1540+ if (cxxrd) {
1541+ for (const CXXBaseSpecifier &base : cxxrd->bases ()) {
1542+ if (base.isVirtual ()) {
1543+ // Ignore virtual bases; if we're laying out for a complete
1544+ // object, we'll lay these out later.
1545+ continue ;
1546+ }
1547+
1548+ const auto *baseDecl = base.getType ()->castAsCXXRecordDecl ();
1549+ // Ignore empty bases.
1550+ if (isEmptyRecordForLayout (cgm.getASTContext (), base.getType ()) ||
1551+ cgm.getASTContext ()
1552+ .getASTRecordLayout (baseDecl)
1553+ .getNonVirtualSize ()
1554+ .isZero ())
1555+ continue ;
1556+
1557+ unsigned fieldIndex = layout.getNonVirtualBaseCIRFieldNo (baseDecl);
1558+ mlir::Type baseType = recordTy.getElementType (fieldIndex);
1559+ elements[fieldIndex] = emitNullConstantForBase (cgm, baseType, baseDecl);
1560+ }
1561+ }
1562+
1563+ // Fill in all the fields.
1564+ for (const FieldDecl *field : rd->fields ()) {
1565+ // Fill in non-bitfields. (Bitfields always use a zero pattern, which we
1566+ // will fill in later.)
1567+ if (!field->isBitField () &&
1568+ !isEmptyFieldForLayout (cgm.getASTContext (), field)) {
1569+ unsigned fieldIndex = layout.getCIRFieldNo (field);
1570+ elements[fieldIndex] = cgm.emitNullConstantAttr (field->getType ());
1571+ }
1572+
1573+ // For unions, stop after the first named field.
1574+ if (rd->isUnion ()) {
1575+ if (field->getIdentifier ())
1576+ break ;
1577+ if (const auto *fieldRD = field->getType ()->getAsRecordDecl ())
1578+ if (fieldRD->findFirstNamedDataMember ())
1579+ break ;
1580+ }
1581+ }
1582+
1583+ // Fill in the virtual bases, if we're working with the complete object.
1584+ if (cxxrd && asCompleteObject) {
1585+ for ([[maybe_unused]] const CXXBaseSpecifier &vbase : cxxrd->vbases ()) {
1586+ cgm.errorNYI (vbase.getSourceRange (), " emitNullConstant: virtual base" );
1587+ return {};
1588+ }
1589+ }
1590+
1591+ // Now go through all other fields and zero them out.
1592+ for (unsigned i = 0 ; i != numElements; ++i) {
1593+ if (!elements[i]) {
1594+ cgm.errorNYI (rd->getSourceRange (), " emitNullConstant: field not zeroed" );
1595+ return {};
1596+ }
1597+ }
1598+
1599+ mlir::MLIRContext *mlirContext = recordTy.getContext ();
1600+ return cir::ConstRecordAttr::get (recordTy,
1601+ mlir::ArrayAttr::get (mlirContext, elements));
1602+ }
1603+
1604+ // / Emit the null constant for a base subobject.
1605+ static mlir::TypedAttr emitNullConstantForBase (CIRGenModule &cgm,
1606+ mlir::Type baseType,
1607+ const CXXRecordDecl *baseDecl) {
1608+ const CIRGenRecordLayout &baseLayout =
1609+ cgm.getTypes ().getCIRGenRecordLayout (baseDecl);
1610+
1611+ // Just zero out bases that don't have any pointer to data members.
1612+ if (baseLayout.isZeroInitializableAsBase ())
1613+ return cgm.getBuilder ().getZeroInitAttr (baseType);
1614+
1615+ // Otherwise, we can just use its null constant.
1616+ return emitNullConstant (cgm, baseDecl, /* asCompleteObject=*/ false );
1617+ }
1618+
15241619mlir::Attribute ConstantEmitter::tryEmitPrivateForVarInit (const VarDecl &d) {
15251620 // Make a quick check if variable can be default NULL initialized
15261621 // and avoid going through rest of code which may do, for c++11,
@@ -1820,23 +1915,32 @@ mlir::Attribute ConstantEmitter::tryEmitPrivate(const APValue &value,
18201915}
18211916
18221917mlir::Value CIRGenModule::emitNullConstant (QualType t, mlir::Location loc) {
1823- if (t->getAs <PointerType>()) {
1824- return builder.getNullPtr (getTypes ().convertTypeForMem (t), loc);
1825- }
1918+ return builder.getConstant (loc, emitNullConstantAttr (t));
1919+ }
1920+
1921+ mlir::TypedAttr CIRGenModule::emitNullConstantAttr (QualType t) {
1922+ if (t->getAs <PointerType>())
1923+ return builder.getConstNullPtrAttr (getTypes ().convertTypeForMem (t));
18261924
18271925 if (getTypes ().isZeroInitializable (t))
1828- return builder.getNullValue (getTypes ().convertTypeForMem (t), loc );
1926+ return builder.getZeroInitAttr (getTypes ().convertTypeForMem (t));
18291927
18301928 if (getASTContext ().getAsConstantArrayType (t)) {
1831- errorNYI (" CIRGenModule::emitNullConstant ConstantArrayType" );
1929+ errorNYI (" CIRGenModule::emitNullConstantAttr ConstantArrayType" );
1930+ return {};
18321931 }
18331932
1834- if (t->isRecordType ())
1835- errorNYI ( " CIRGenModule ::emitNullConstant RecordType " );
1933+ if (const RecordType *rt = t->getAs <RecordType> ())
1934+ return ::emitNullConstant (* this , rt-> getDecl (), /* asCompleteObject= */ true );
18361935
18371936 assert (t->isMemberDataPointerType () &&
18381937 " Should only see pointers to data members here!" );
18391938
1840- errorNYI (" CIRGenModule::emitNullConstant unsupported type" );
1939+ errorNYI (" CIRGenModule::emitNullConstantAttr unsupported type" );
18411940 return {};
18421941}
1942+
1943+ mlir::TypedAttr
1944+ CIRGenModule::emitNullConstantForBase (const CXXRecordDecl *record) {
1945+ return ::emitNullConstant (*this , record, false );
1946+ }
0 commit comments