@@ -176,6 +176,69 @@ bool ConstantAggregateBuilder::add(mlir::TypedAttr typedAttr, CharUnits offset,
176176 return false ;
177177}
178178
179+ bool ConstantAggregateBuilder::addBits (llvm::APInt bits, uint64_t offsetInBits,
180+ bool allowOverwrite) {
181+ const ASTContext &astContext = cgm.getASTContext ();
182+ const uint64_t charWidth = cgm.getASTContext ().getCharWidth ();
183+ mlir::Type charTy = cgm.getBuilder ().getUIntNTy (charWidth);
184+
185+ // Offset of where we want the first bit to go within the bits of the
186+ // current char.
187+ unsigned offsetWithinChar = offsetInBits % charWidth;
188+
189+ // We split bit-fields up into individual bytes. Walk over the bytes and
190+ // update them.
191+ for (CharUnits offsetInChars =
192+ astContext.toCharUnitsFromBits (offsetInBits - offsetWithinChar);
193+ /* */ ; ++offsetInChars) {
194+ // Number of bits we want to fill in this char.
195+ unsigned wantedBits =
196+ std::min ((uint64_t )bits.getBitWidth (), charWidth - offsetWithinChar);
197+
198+ // Get a char containing the bits we want in the right places. The other
199+ // bits have unspecified values.
200+ llvm::APInt bitsThisChar = bits;
201+ if (bitsThisChar.getBitWidth () < charWidth)
202+ bitsThisChar = bitsThisChar.zext (charWidth);
203+ if (cgm.getDataLayout ().isBigEndian ()) {
204+ // Figure out how much to shift by. We may need to left-shift if we have
205+ // less than one byte of Bits left.
206+ int shift = bits.getBitWidth () - charWidth + offsetWithinChar;
207+ if (shift > 0 )
208+ bitsThisChar.lshrInPlace (shift);
209+ else if (shift < 0 )
210+ bitsThisChar = bitsThisChar.shl (-shift);
211+ } else {
212+ bitsThisChar = bitsThisChar.shl (offsetWithinChar);
213+ }
214+ if (bitsThisChar.getBitWidth () > charWidth)
215+ bitsThisChar = bitsThisChar.trunc (charWidth);
216+
217+ if (wantedBits == charWidth) {
218+ // Got a full byte: just add it directly.
219+ add (cir::IntAttr::get (charTy, bitsThisChar), offsetInChars,
220+ allowOverwrite);
221+ } else {
222+ cgm.errorNYI (" partial byte bitfield updates" );
223+ return false ;
224+ }
225+
226+ // Stop if we've added all the bits.
227+ if (wantedBits == bits.getBitWidth ())
228+ break ;
229+
230+ // Remove the consumed bits from Bits.
231+ if (!cgm.getDataLayout ().isBigEndian ())
232+ bits.lshrInPlace (wantedBits);
233+ bits = bits.trunc (bits.getBitWidth () - wantedBits);
234+
235+ // The remaining bits go at the start of the following bytes.
236+ offsetWithinChar = 0 ;
237+ }
238+
239+ return true ;
240+ }
241+
179242mlir::Attribute
180243ConstantAggregateBuilder::buildFrom (CIRGenModule &cgm, ArrayRef<Element> elems,
181244 CharUnits startOffset, CharUnits size,
@@ -301,6 +364,9 @@ class ConstRecordBuilder {
301364 bool appendBytes (CharUnits fieldOffsetInChars, mlir::TypedAttr initCst,
302365 bool allowOverwrite = false );
303366
367+ bool appendBitField (const FieldDecl *field, uint64_t fieldOffset,
368+ cir::IntAttr ci, bool allowOverwrite = false );
369+
304370 bool build (InitListExpr *ile, bool allowOverwrite);
305371 bool build (const APValue &val, const RecordDecl *rd, bool isPrimaryBase,
306372 const CXXRecordDecl *vTableClass, CharUnits baseOffset);
@@ -325,6 +391,29 @@ bool ConstRecordBuilder::appendBytes(CharUnits fieldOffsetInChars,
325391 return builder.add (initCst, startOffset + fieldOffsetInChars, allowOverwrite);
326392}
327393
394+ bool ConstRecordBuilder::appendBitField (const FieldDecl *field,
395+ uint64_t fieldOffset, cir::IntAttr ci,
396+ bool allowOverwrite) {
397+ const auto &rl = cgm.getTypes ().getCIRGenRecordLayout (field->getParent ());
398+ const auto &info = rl.getBitFieldInfo (field);
399+ llvm::APInt fieldValue = ci.getValue ();
400+
401+ // Promote the size of FieldValue if necessary
402+ // FIXME: This should never occur, but currently it can because initializer
403+ // constants are cast to bool, and because clang is not enforcing bitfield
404+ // width limits.
405+ if (info.size > fieldValue.getBitWidth ())
406+ fieldValue = fieldValue.zext (info.size );
407+
408+ // Truncate the size of FieldValue to the bit field size.
409+ if (info.size < fieldValue.getBitWidth ())
410+ fieldValue = fieldValue.trunc (info.size );
411+
412+ return builder.addBits (fieldValue,
413+ cgm.getASTContext ().toBits (startOffset) + fieldOffset,
414+ allowOverwrite);
415+ }
416+
328417bool ConstRecordBuilder::build (InitListExpr *ile, bool allowOverwrite) {
329418 RecordDecl *rd = ile->getType ()
330419 ->castAs <clang::RecordType>()
@@ -407,12 +496,14 @@ bool ConstRecordBuilder::build(InitListExpr *ile, bool allowOverwrite) {
407496 } else {
408497 // Otherwise we have a bitfield.
409498 if (auto constInt = dyn_cast<cir::IntAttr>(eltInit)) {
410- assert (!cir::MissingFeatures::bitfields ());
411- cgm.errorNYI (field->getSourceRange (), " bitfields" );
499+ if (!appendBitField (field, layout.getFieldOffset (index), constInt,
500+ allowOverwrite))
501+ return false ;
502+ } else {
503+ // We are trying to initialize a bitfield with a non-trivial constant,
504+ // this must require run-time code.
505+ return false ;
412506 }
413- // We are trying to initialize a bitfield with a non-trivial constant,
414- // this must require run-time code.
415- return false ;
416507 }
417508 }
418509
@@ -510,8 +601,16 @@ bool ConstRecordBuilder::build(const APValue &val, const RecordDecl *rd,
510601 if (field->hasAttr <NoUniqueAddressAttr>())
511602 allowOverwrite = true ;
512603 } else {
513- assert (!cir::MissingFeatures::bitfields ());
514- cgm.errorNYI (field->getSourceRange (), " bitfields" );
604+ // Otherwise we have a bitfield.
605+ if (auto constInt = dyn_cast<cir::IntAttr>(eltInit)) {
606+ if (!appendBitField (field, layout.getFieldOffset (index) + offsetBits,
607+ constInt, allowOverwrite))
608+ return false ;
609+ } else {
610+ // We are trying to initialize a bitfield with a non-trivial constant,
611+ // this must require run-time code.
612+ return false ;
613+ }
515614 }
516615 }
517616
0 commit comments