Skip to content

Commit c1731b1

Browse files
committed
[CIR][CIRGen][NFC] More skeleton for building constants
1 parent cb0cb34 commit c1731b1

File tree

3 files changed

+82
-7
lines changed

3 files changed

+82
-7
lines changed

clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp

+18-1
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,24 @@ static void buildNullBaseClassInitialization(CIRGenFunction &CGF,
386386
Stores.emplace_back(SplitAfterOffset, SplitAfterSize);
387387
}
388388

389-
llvm_unreachable("NYI");
389+
// If the type contains a pointer to data member we can't memset it to zero.
390+
// Instead, create a null constant and copy it to the destination.
391+
// TODO: there are other patterns besides zero that we can usefully memset,
392+
// like -1, which happens to be the pattern used by member-pointers.
393+
// TODO: isZeroInitializable can be over-conservative in the case where a
394+
// virtual base contains a member pointer.
395+
// TODO(cir): `nullConstantForBase` might be better off as a value instead
396+
// of an mlir::TypedAttr? Once this moves out of skeleton, make sure to double
397+
// check on what's better.
398+
mlir::Attribute nullConstantForBase = CGF.CGM.buildNullConstantForBase(Base);
399+
if (!CGF.getBuilder().isNullValue(nullConstantForBase)) {
400+
llvm_unreachable("NYI");
401+
// Otherwise, just memset the whole thing to zero. This is legal
402+
// because in LLVM, all default initializers (other than the ones we just
403+
// handled above) are guaranteed to have a bit pattern of all zeros.
404+
} else {
405+
llvm_unreachable("NYI");
406+
}
390407
}
391408

392409
void CIRGenFunction::buildCXXConstructExpr(const CXXConstructExpr *E,

clang/lib/CIR/CodeGen/CIRGenExprConst.cpp

+63-5
Original file line numberDiff line numberDiff line change
@@ -1958,13 +1958,71 @@ mlir::Attribute ConstantEmitter::emitNullForMemory(mlir::Location loc,
19581958
return emitForMemory(CGM, cstOp.getValue(), T);
19591959
}
19601960

1961-
static mlir::Value buildNullConstant(CIRGenModule &CGM,
1962-
const RecordDecl *record,
1963-
bool asCompleteObject) {
1964-
llvm_unreachable("NYI");
1961+
static mlir::TypedAttr buildNullConstant(CIRGenModule &CGM,
1962+
const RecordDecl *record,
1963+
bool asCompleteObject) {
1964+
const CIRGenRecordLayout &layout =
1965+
CGM.getTypes().getCIRGenRecordLayout(record);
1966+
mlir::Type ty = (asCompleteObject ? layout.getCIRType()
1967+
: layout.getBaseSubobjectCIRType());
1968+
auto structure = dyn_cast<mlir::cir::StructType>(ty);
1969+
assert(structure && "expected");
1970+
1971+
unsigned numElements = structure.getNumElements();
1972+
SmallVector<mlir::Attribute, 4> elements(numElements);
1973+
1974+
auto CXXR = dyn_cast<CXXRecordDecl>(record);
1975+
// Fill in all the bases.
1976+
if (CXXR) {
1977+
for (const auto &I : CXXR->bases()) {
1978+
if (I.isVirtual()) {
1979+
// Ignore virtual bases; if we're laying out for a complete
1980+
// object, we'll lay these out later.
1981+
continue;
1982+
}
1983+
llvm_unreachable("NYI");
1984+
}
1985+
}
1986+
1987+
// Fill in all the fields.
1988+
for (const auto *Field : record->fields()) {
1989+
// Fill in non-bitfields. (Bitfields always use a zero pattern, which we
1990+
// will fill in later.)
1991+
if (!Field->isBitField()) {
1992+
// TODO(cir) check for !isEmptyFieldForLayout(CGM.getContext(), Field))
1993+
llvm_unreachable("NYI");
1994+
}
1995+
1996+
// For unions, stop after the first named field.
1997+
if (record->isUnion()) {
1998+
if (Field->getIdentifier())
1999+
break;
2000+
if (const auto *FieldRD = Field->getType()->getAsRecordDecl())
2001+
if (FieldRD->findFirstNamedDataMember())
2002+
break;
2003+
}
2004+
}
2005+
2006+
// Fill in the virtual bases, if we're working with the complete object.
2007+
if (CXXR && asCompleteObject) {
2008+
for ([[maybe_unused]] const auto &I : CXXR->vbases()) {
2009+
llvm_unreachable("NYI");
2010+
}
2011+
}
2012+
2013+
// Now go through all other fields and zero them out.
2014+
for (unsigned i = 0; i != numElements; ++i) {
2015+
if (!elements[i]) {
2016+
llvm_unreachable("NYI");
2017+
}
2018+
}
2019+
2020+
mlir::MLIRContext *mlirCtx = structure.getContext();
2021+
return mlir::cir::ConstStructAttr::get(
2022+
mlirCtx, structure, mlir::ArrayAttr::get(mlirCtx, elements));
19652023
}
19662024

1967-
mlir::Value
2025+
mlir::TypedAttr
19682026
CIRGenModule::buildNullConstantForBase(const CXXRecordDecl *Record) {
19692027
return ::buildNullConstant(*this, Record, false);
19702028
}

clang/lib/CIR/CodeGen/CIRGenModule.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -608,7 +608,7 @@ class CIRGenModule : public CIRGenTypeCache {
608608

609609
/// Return a null constant appropriate for zero-initializing a base class with
610610
/// the given type. This is usually, but not always, an LLVM null constant.
611-
mlir::Value buildNullConstantForBase(const CXXRecordDecl *Record);
611+
mlir::TypedAttr buildNullConstantForBase(const CXXRecordDecl *Record);
612612

613613
mlir::Value buildMemberPointerConstant(const UnaryOperator *E);
614614

0 commit comments

Comments
 (0)