aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CIR/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CIR/CodeGen')
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenDecl.cpp22
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp64
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp6
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenFunction.h28
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp19
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenOpenACCRecipe.cpp46
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenOpenACCRecipe.h24
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp23
8 files changed, 98 insertions, 134 deletions
diff --git a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
index 10b8255..563a753 100644
--- a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
@@ -35,8 +35,8 @@ CIRGenFunction::emitAutoVarAlloca(const VarDecl &d,
getContext().getLangOpts().ElideConstructors && d.isNRVOVariable();
CIRGenFunction::AutoVarEmission emission(d);
- emission.IsEscapingByRef = d.isEscapingByref();
- if (emission.IsEscapingByRef)
+ emission.isEscapingByRef = d.isEscapingByref();
+ if (emission.isEscapingByRef)
cgm.errorNYI(d.getSourceRange(),
"emitAutoVarDecl: decl escaping by reference");
@@ -78,7 +78,7 @@ CIRGenFunction::emitAutoVarAlloca(const VarDecl &d,
alignment);
}
- emission.Addr = address;
+ emission.addr = address;
setAddrOfLocalVar(&d, address);
return emission;
@@ -101,13 +101,13 @@ bool CIRGenFunction::isTrivialInitializer(const Expr *init) {
void CIRGenFunction::emitAutoVarInit(
const CIRGenFunction::AutoVarEmission &emission) {
- assert(emission.Variable && "emission was not valid!");
+ assert(emission.variable && "emission was not valid!");
// If this was emitted as a global constant, we're done.
if (emission.wasEmittedAsGlobal())
return;
- const VarDecl &d = *emission.Variable;
+ const VarDecl &d = *emission.variable;
QualType type = d.getType();
@@ -124,7 +124,7 @@ void CIRGenFunction::emitAutoVarInit(
return;
}
- const Address addr = emission.Addr;
+ const Address addr = emission.addr;
// Check whether this is a byref variable that's potentially
// captured and moved by its own initializer. If so, we'll need to
@@ -153,7 +153,7 @@ void CIRGenFunction::emitAutoVarInit(
}
mlir::Attribute constant;
- if (emission.IsConstantAggregate ||
+ if (emission.isConstantAggregate ||
d.mightBeUsableInConstantExpressions(getContext())) {
// FIXME: Differently from LLVM we try not to emit / lower too much
// here for CIR since we are interested in seeing the ctor in some
@@ -196,7 +196,7 @@ void CIRGenFunction::emitAutoVarInit(
// FIXME(cir): migrate most of this file to use mlir::TypedAttr directly.
auto typedConstant = mlir::dyn_cast<mlir::TypedAttr>(constant);
assert(typedConstant && "expected typed attribute");
- if (!emission.IsConstantAggregate) {
+ if (!emission.isConstantAggregate) {
// For simple scalar/complex initialization, store the value directly.
LValue lv = makeAddrLValue(addr, type);
assert(init && "expected initializer");
@@ -209,7 +209,7 @@ void CIRGenFunction::emitAutoVarInit(
void CIRGenFunction::emitAutoVarCleanups(
const CIRGenFunction::AutoVarEmission &emission) {
- const VarDecl &d = *emission.Variable;
+ const VarDecl &d = *emission.variable;
// Check the type for a cleanup.
if (QualType::DestructionKind dtorKind = d.needsDestruction(getContext()))
@@ -821,7 +821,7 @@ void CIRGenFunction::emitAutoVarTypeCleanup(
// original stack object, not the possibly forwarded object.
Address addr = emission.getObjectAddress(*this);
- const VarDecl *var = emission.Variable;
+ const VarDecl *var = emission.variable;
QualType type = var->getType();
CleanupKind cleanupKind = NormalAndEHCleanup;
@@ -834,7 +834,7 @@ void CIRGenFunction::emitAutoVarTypeCleanup(
case QualType::DK_cxx_destructor:
// If there's an NRVO flag on the emission, we need a different
// cleanup.
- if (emission.NRVOFlag) {
+ if (emission.nrvoFlag) {
cgm.errorNYI(var->getSourceRange(), "emitAutoVarTypeCleanup: NRVO");
return;
}
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp b/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp
index 83208bf..7989ad2 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp
@@ -210,60 +210,6 @@ RValue CIRGenFunction::emitCXXMemberOrOperatorCall(
return emitCall(fnInfo, callee, returnValue, args, nullptr, loc);
}
-namespace {
-/// The parameters to pass to a usual operator delete.
-struct UsualDeleteParams {
- TypeAwareAllocationMode typeAwareDelete = TypeAwareAllocationMode::No;
- bool destroyingDelete = false;
- bool size = false;
- AlignedAllocationMode alignment = AlignedAllocationMode::No;
-};
-} // namespace
-
-// FIXME(cir): this should be shared with LLVM codegen
-static UsualDeleteParams getUsualDeleteParams(const FunctionDecl *fd) {
- UsualDeleteParams params;
-
- const FunctionProtoType *fpt = fd->getType()->castAs<FunctionProtoType>();
- auto ai = fpt->param_type_begin(), ae = fpt->param_type_end();
-
- if (fd->isTypeAwareOperatorNewOrDelete()) {
- params.typeAwareDelete = TypeAwareAllocationMode::Yes;
- assert(ai != ae);
- ++ai;
- }
-
- // The first argument after the type-identity parameter (if any) is
- // always a void* (or C* for a destroying operator delete for class
- // type C).
- ++ai;
-
- // The next parameter may be a std::destroying_delete_t.
- if (fd->isDestroyingOperatorDelete()) {
- params.destroyingDelete = true;
- assert(ai != ae);
- ++ai;
- }
-
- // Figure out what other parameters we should be implicitly passing.
- if (ai != ae && (*ai)->isIntegerType()) {
- params.size = true;
- ++ai;
- } else {
- assert(!isTypeAwareAllocation(params.typeAwareDelete));
- }
-
- if (ai != ae && (*ai)->isAlignValT()) {
- params.alignment = AlignedAllocationMode::Yes;
- ++ai;
- } else {
- assert(!isTypeAwareAllocation(params.typeAwareDelete));
- }
-
- assert(ai == ae && "unexpected usual deallocation function parameter");
- return params;
-}
-
static mlir::Value emitCXXNewAllocSize(CIRGenFunction &cgf, const CXXNewExpr *e,
unsigned minElements,
mlir::Value &numElements,
@@ -616,11 +562,11 @@ void CIRGenFunction::emitDeleteCall(const FunctionDecl *deleteFD,
const auto *deleteFTy = deleteFD->getType()->castAs<FunctionProtoType>();
CallArgList deleteArgs;
- UsualDeleteParams params = getUsualDeleteParams(deleteFD);
+ UsualDeleteParams params = deleteFD->getUsualDeleteParams();
auto paramTypeIt = deleteFTy->param_type_begin();
// Pass std::type_identity tag if present
- if (isTypeAwareAllocation(params.typeAwareDelete))
+ if (isTypeAwareAllocation(params.TypeAwareDelete))
cgm.errorNYI(deleteFD->getSourceRange(),
"emitDeleteCall: type aware delete");
@@ -631,12 +577,12 @@ void CIRGenFunction::emitDeleteCall(const FunctionDecl *deleteFD,
deleteArgs.add(RValue::get(deletePtr), argTy);
// Pass the std::destroying_delete tag if present.
- if (params.destroyingDelete)
+ if (params.DestroyingDelete)
cgm.errorNYI(deleteFD->getSourceRange(),
"emitDeleteCall: destroying delete");
// Pass the size if the delete function has a size_t parameter.
- if (params.size) {
+ if (params.Size) {
QualType sizeType = *paramTypeIt++;
CharUnits deleteTypeSize = getContext().getTypeSizeInChars(deleteTy);
assert(mlir::isa<cir::IntType>(convertType(sizeType)) &&
@@ -648,7 +594,7 @@ void CIRGenFunction::emitDeleteCall(const FunctionDecl *deleteFD,
}
// Pass the alignment if the delete function has an align_val_t parameter.
- if (isAlignedAllocation(params.alignment))
+ if (isAlignedAllocation(params.Alignment))
cgm.errorNYI(deleteFD->getSourceRange(),
"emitDeleteCall: aligned allocation");
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index f4bbced..500007f 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -2151,8 +2151,10 @@ mlir::Value ScalarExprEmitter::VisitRealImag(const UnaryOperator *e,
}
if (e->getOpcode() == UO_Real) {
- return promotionTy.isNull() ? Visit(op)
- : cgf.emitPromotedScalarExpr(op, promotionTy);
+ mlir::Value operand = promotionTy.isNull()
+ ? Visit(op)
+ : cgf.emitPromotedScalarExpr(op, promotionTy);
+ return builder.createComplexReal(loc, operand);
}
// __imag on a scalar returns zero. Emit the subexpr to ensure side
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index c0ed8b4..cb7cf98 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -479,55 +479,55 @@ public:
ConstantEmission tryEmitAsConstant(const MemberExpr *me);
struct AutoVarEmission {
- const clang::VarDecl *Variable;
+ const clang::VarDecl *variable;
/// The address of the alloca for languages with explicit address space
/// (e.g. OpenCL) or alloca casted to generic pointer for address space
/// agnostic languages (e.g. C++). Invalid if the variable was emitted
/// as a global constant.
- Address Addr;
+ Address addr;
/// True if the variable is of aggregate type and has a constant
/// initializer.
- bool IsConstantAggregate = false;
+ bool isConstantAggregate = false;
/// True if the variable is a __block variable that is captured by an
/// escaping block.
- bool IsEscapingByRef = false;
+ bool isEscapingByRef = false;
/// True if the variable was emitted as an offload recipe, and thus doesn't
/// have the same sort of alloca initialization.
- bool EmittedAsOffload = false;
+ bool emittedAsOffload = false;
- mlir::Value NRVOFlag{};
+ mlir::Value nrvoFlag{};
struct Invalid {};
- AutoVarEmission(Invalid) : Variable(nullptr), Addr(Address::invalid()) {}
+ AutoVarEmission(Invalid) : variable(nullptr), addr(Address::invalid()) {}
AutoVarEmission(const clang::VarDecl &variable)
- : Variable(&variable), Addr(Address::invalid()) {}
+ : variable(&variable), addr(Address::invalid()) {}
static AutoVarEmission invalid() { return AutoVarEmission(Invalid()); }
- bool wasEmittedAsGlobal() const { return !Addr.isValid(); }
+ bool wasEmittedAsGlobal() const { return !addr.isValid(); }
- bool wasEmittedAsOffloadClause() const { return EmittedAsOffload; }
+ bool wasEmittedAsOffloadClause() const { return emittedAsOffload; }
/// Returns the raw, allocated address, which is not necessarily
/// the address of the object itself. It is casted to default
/// address space for address space agnostic languages.
- Address getAllocatedAddress() const { return Addr; }
+ Address getAllocatedAddress() const { return addr; }
// Changes the stored address for the emission. This function should only
// be used in extreme cases, and isn't required to model normal AST
// initialization/variables.
- void setAllocatedAddress(Address A) { Addr = A; }
+ void setAllocatedAddress(Address a) { addr = a; }
/// Returns the address of the object within this declaration.
/// Note that this does not chase the forwarding pointer for
/// __block decls.
Address getObjectAddress(CIRGenFunction &cgf) const {
- if (!IsEscapingByRef)
- return Addr;
+ if (!isEscapingByRef)
+ return addr;
assert(!cir::MissingFeatures::opAllocaEscapeByReference());
return Address::invalid();
diff --git a/clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp b/clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp
index f22f3e8..3d86f71 100644
--- a/clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp
@@ -1001,7 +1001,7 @@ public:
OpenACCRecipeBuilder<mlir::acc::PrivateRecipeOp>(cgf, builder)
.getOrCreateRecipe(
cgf.getContext(), recipeInsertLocation, varExpr,
- varRecipe.AllocaDecl, varRecipe.InitExpr,
+ varRecipe.AllocaDecl,
/*temporary=*/nullptr, OpenACCReductionOperator::Invalid,
Decl::castToDeclContext(cgf.curFuncDecl), opInfo.origType,
opInfo.bounds.size(), opInfo.boundTypes, opInfo.baseType,
@@ -1036,20 +1036,13 @@ public:
{
mlir::OpBuilder::InsertionGuard guardCase(builder);
- // TODO: OpenACC: At the moment this is a bit of a hacky way of doing
- // this, and won't work when we get to bounds/etc. Do this for now to
- // limit the scope of this refactor.
- VarDecl *allocaDecl = varRecipe.AllocaDecl;
- allocaDecl->setInit(varRecipe.InitExpr);
- allocaDecl->setInitStyle(VarDecl::CallInit);
auto recipe =
OpenACCRecipeBuilder<mlir::acc::FirstprivateRecipeOp>(cgf,
builder)
.getOrCreateRecipe(
cgf.getContext(), recipeInsertLocation, varExpr,
- varRecipe.AllocaDecl, varRecipe.InitExpr,
- varRecipe.InitFromTemporary,
+ varRecipe.AllocaDecl, varRecipe.InitFromTemporary,
OpenACCReductionOperator::Invalid,
Decl::castToDeclContext(cgf.curFuncDecl), opInfo.origType,
opInfo.bounds.size(), opInfo.boundTypes, opInfo.baseType,
@@ -1086,18 +1079,12 @@ public:
{
mlir::OpBuilder::InsertionGuard guardCase(builder);
- // TODO: OpenACC: At the moment this is a bit of a hacky way of doing
- // this, and won't work when we get to bounds/etc. Do this for now to
- // limit the scope of this refactor.
- VarDecl *allocaDecl = varRecipe.AllocaDecl;
- allocaDecl->setInit(varRecipe.InitExpr);
- allocaDecl->setInitStyle(VarDecl::CallInit);
auto recipe =
OpenACCRecipeBuilder<mlir::acc::ReductionRecipeOp>(cgf, builder)
.getOrCreateRecipe(
cgf.getContext(), recipeInsertLocation, varExpr,
- varRecipe.AllocaDecl, varRecipe.InitExpr,
+ varRecipe.AllocaDecl,
/*temporary=*/nullptr, clause.getReductionOp(),
Decl::castToDeclContext(cgf.curFuncDecl), opInfo.origType,
opInfo.bounds.size(), opInfo.boundTypes, opInfo.baseType,
diff --git a/clang/lib/CIR/CodeGen/CIRGenOpenACCRecipe.cpp b/clang/lib/CIR/CodeGen/CIRGenOpenACCRecipe.cpp
index e603884..ea6ea2c 100644
--- a/clang/lib/CIR/CodeGen/CIRGenOpenACCRecipe.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenOpenACCRecipe.cpp
@@ -400,6 +400,32 @@ void OpenACCRecipeBuilderBase::createRecipeDestroySection(
mlir::acc::YieldOp::create(builder, locEnd);
}
+void OpenACCRecipeBuilderBase::makeBoundsInit(
+ mlir::Value alloca, mlir::Location loc, mlir::Block *block,
+ const VarDecl *allocaDecl, QualType origType, bool isInitSection) {
+ mlir::OpBuilder::InsertionGuard guardCase(builder);
+ builder.setInsertionPointToEnd(block);
+ CIRGenFunction::LexicalScope ls(cgf, loc, block);
+
+ CIRGenFunction::AutoVarEmission tempDeclEmission{*allocaDecl};
+ tempDeclEmission.emittedAsOffload = true;
+
+ // The init section is the only one of the handful that only has a single
+ // argument for the 'type', so we have to drop 1 for init, and future calls
+ // to this will need to drop 2.
+ llvm::MutableArrayRef<mlir::BlockArgument> boundsRange =
+ block->getArguments().drop_front(isInitSection ? 1 : 2);
+
+ mlir::Value subscriptedValue = alloca;
+ for (mlir::BlockArgument boundArg : llvm::reverse(boundsRange))
+ subscriptedValue = createBoundsLoop(subscriptedValue, boundArg, loc,
+ /*inverse=*/false);
+
+ tempDeclEmission.setAllocatedAddress(
+ Address{subscriptedValue, cgf.convertType(origType),
+ cgf.getContext().getDeclAlign(allocaDecl)});
+ cgf.emitAutoVarInit(tempDeclEmission);
+}
// TODO: OpenACC: When we get this implemented for the reduction/firstprivate,
// this might end up re-merging with createRecipeInitCopy. For now, keep it
@@ -409,7 +435,7 @@ void OpenACCRecipeBuilderBase::createPrivateInitRecipe(
mlir::Location loc, mlir::Location locEnd, SourceRange exprRange,
mlir::Value mainOp, mlir::acc::PrivateRecipeOp recipe, size_t numBounds,
llvm::ArrayRef<QualType> boundTypes, const VarDecl *allocaDecl,
- QualType origType, const Expr *initExpr) {
+ QualType origType) {
assert(allocaDecl && "Required recipe variable not set?");
CIRGenFunction::DeclMapRevertingRAII declMapRAII{cgf, allocaDecl};
@@ -442,11 +468,17 @@ void OpenACCRecipeBuilderBase::createPrivateInitRecipe(
cgf.emitAutoVarAlloca(*allocaDecl, builder.saveInsertionPoint());
cgf.emitAutoVarInit(tempDeclEmission);
} else {
- makeBoundsAlloca(block, exprRange, loc, "openacc.private.init", numBounds,
- boundTypes);
-
- if (initExpr)
- cgf.cgm.errorNYI(exprRange, "private-init with bounds initialization");
+ mlir::Value alloca = makeBoundsAlloca(
+ block, exprRange, loc, "openacc.private.init", numBounds, boundTypes);
+
+ // If the initializer is trivial, there is nothing to do here, so save
+ // ourselves some effort.
+ if (allocaDecl->getInit() &&
+ (!cgf.isTrivialInitializer(allocaDecl->getInit()) ||
+ cgf.getContext().getLangOpts().getTrivialAutoVarInit() !=
+ LangOptions::TrivialAutoVarInitKind::Uninitialized))
+ makeBoundsInit(alloca, loc, block, allocaDecl, origType,
+ /*isInitSection=*/true);
}
mlir::acc::YieldOp::create(builder, locEnd);
@@ -473,7 +505,7 @@ void OpenACCRecipeBuilderBase::createFirstprivateRecipeCopy(
// that instead of the variable in the other block.
tempDeclEmission.setAllocatedAddress(
Address{toArg, elementTy, cgf.getContext().getDeclAlign(varRecipe)});
- tempDeclEmission.EmittedAsOffload = true;
+ tempDeclEmission.emittedAsOffload = true;
CIRGenFunction::DeclMapRevertingRAII declMapRAII{cgf, temporary};
cgf.setAddrOfLocalVar(
diff --git a/clang/lib/CIR/CodeGen/CIRGenOpenACCRecipe.h b/clang/lib/CIR/CodeGen/CIRGenOpenACCRecipe.h
index d802ccb..a05b0bd 100644
--- a/clang/lib/CIR/CodeGen/CIRGenOpenACCRecipe.h
+++ b/clang/lib/CIR/CodeGen/CIRGenOpenACCRecipe.h
@@ -35,6 +35,10 @@ class OpenACCRecipeBuilderBase {
size_t numBounds,
llvm::ArrayRef<QualType> boundTypes);
+ void makeBoundsInit(mlir::Value alloca, mlir::Location loc,
+ mlir::Block *block, const VarDecl *allocaDecl,
+ QualType origType, bool isInitSection);
+
protected:
CIRGen::CIRGenFunction &cgf;
CIRGen::CIRGenBuilderTy &builder;
@@ -66,8 +70,7 @@ protected:
mlir::acc::PrivateRecipeOp recipe,
size_t numBounds,
llvm::ArrayRef<QualType> boundTypes,
- const VarDecl *allocaDecl, QualType origType,
- const Expr *initExpr);
+ const VarDecl *allocaDecl, QualType origType);
void createRecipeDestroySection(mlir::Location loc, mlir::Location locEnd,
mlir::Value mainOp, CharUnits alignment,
@@ -208,15 +211,12 @@ public:
OpenACCRecipeBuilder(CIRGen::CIRGenFunction &cgf,
CIRGen::CIRGenBuilderTy &builder)
: OpenACCRecipeBuilderBase(cgf, builder) {}
- RecipeTy getOrCreateRecipe(ASTContext &astCtx,
- mlir::OpBuilder::InsertPoint &insertLocation,
- const Expr *varRef, const VarDecl *varRecipe,
- const Expr *initExpr, const VarDecl *temporary,
- OpenACCReductionOperator reductionOp,
- DeclContext *dc, QualType origType,
- size_t numBounds,
- llvm::ArrayRef<QualType> boundTypes,
- QualType baseType, mlir::Value mainOp) {
+ RecipeTy getOrCreateRecipe(
+ ASTContext &astCtx, mlir::OpBuilder::InsertPoint &insertLocation,
+ const Expr *varRef, const VarDecl *varRecipe, const VarDecl *temporary,
+ OpenACCReductionOperator reductionOp, DeclContext *dc, QualType origType,
+ size_t numBounds, llvm::ArrayRef<QualType> boundTypes, QualType baseType,
+ mlir::Value mainOp) {
assert(!varRecipe->getType()->isSpecificBuiltinType(
BuiltinType::ArraySection) &&
"array section shouldn't make it to recipe creation");
@@ -262,7 +262,7 @@ public:
if constexpr (std::is_same_v<RecipeTy, mlir::acc::PrivateRecipeOp>) {
createPrivateInitRecipe(loc, locEnd, varRef->getSourceRange(), mainOp,
recipe, numBounds, boundTypes, varRecipe,
- origType, initExpr);
+ origType);
} else {
createRecipeInitCopy(loc, locEnd, varRef->getSourceRange(), mainOp,
recipe, varRecipe, temporary);
diff --git a/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp b/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp
index a762881..87f2340 100644
--- a/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp
@@ -296,9 +296,8 @@ void CIRRecordLowering::lower(bool nonVirtualBaseType) {
}
llvm::stable_sort(members);
- // TODO: implement clipTailPadding once bitfields are implemented
- assert(!cir::MissingFeatures::bitfields());
- assert(!cir::MissingFeatures::recordZeroInit());
+ // TODO: Verify bitfield clipping
+ assert(!cir::MissingFeatures::checkBitfieldClipping());
members.push_back(makeStorageInfo(size, getUIntNType(8)));
determinePacked(nonVirtualBaseType);
@@ -319,9 +318,11 @@ void CIRRecordLowering::fillOutputFields() {
fieldIdxMap[member.fieldDecl->getCanonicalDecl()] =
fieldTypes.size() - 1;
// A field without storage must be a bitfield.
- assert(!cir::MissingFeatures::bitfields());
- if (!member.data)
+ if (!member.data) {
+ assert(member.fieldDecl &&
+ "member.data is a nullptr so member.fieldDecl should not be");
setBitFieldInfo(member.fieldDecl, member.offset, fieldTypes.back());
+ }
} else if (member.kind == MemberInfo::InfoKind::Base) {
nonVirtualBases[member.cxxRecordDecl] = fieldTypes.size() - 1;
} else if (member.kind == MemberInfo::InfoKind::VBase) {
@@ -615,7 +616,7 @@ void CIRRecordLowering::determinePacked(bool nvBaseType) {
continue;
// If any member falls at an offset that it not a multiple of its alignment,
// then the entire record must be packed.
- if (member.offset % getAlignment(member.data))
+ if (!member.offset.isMultipleOf(getAlignment(member.data)))
packed = true;
if (member.offset < nvSize)
nvAlignment = std::max(nvAlignment, getAlignment(member.data));
@@ -623,12 +624,12 @@ void CIRRecordLowering::determinePacked(bool nvBaseType) {
}
// If the size of the record (the capstone's offset) is not a multiple of the
// record's alignment, it must be packed.
- if (members.back().offset % alignment)
+ if (!members.back().offset.isMultipleOf(alignment))
packed = true;
// If the non-virtual sub-object is not a multiple of the non-virtual
// sub-object's alignment, it must be packed. We cannot have a packed
// non-virtual sub-object and an unpacked complete object or vise versa.
- if (nvSize % nvAlignment)
+ if (!nvSize.isMultipleOf(nvAlignment))
packed = true;
// Update the alignment of the sentinel.
if (!packed)
@@ -697,13 +698,9 @@ CIRGenTypes::computeRecordLayout(const RecordDecl *rd, cir::RecordType *ty) {
ty ? *ty : cir::RecordType{}, baseTy ? baseTy : cir::RecordType{},
(bool)lowering.zeroInitializable, (bool)lowering.zeroInitializableAsBase);
- assert(!cir::MissingFeatures::recordZeroInit());
-
rl->nonVirtualBases.swap(lowering.nonVirtualBases);
rl->completeObjectVirtualBases.swap(lowering.virtualBases);
- assert(!cir::MissingFeatures::bitfields());
-
// Add all the field numbers.
rl->fieldIdxMap.swap(lowering.fieldIdxMap);
@@ -824,7 +821,7 @@ void CIRRecordLowering::lowerUnion() {
appendPaddingBytes(layoutSize - getSize(storageType));
// Set packed if we need it.
- if (layoutSize % getAlignment(storageType))
+ if (!layoutSize.isMultipleOf(getAlignment(storageType)))
packed = true;
}