================
@@ -15730,3 +15731,276 @@ void ASTContext::recordOffsetOfEvaluation(const
OffsetOfExpr *E) {
if (FieldDecl *FD = Comp.getField(); isPFPField(FD))
PFPFieldsWithEvaluatedOffset.insert(FD);
}
+
+namespace {
+// PaddingCalculator is a utility class that calculates the padding bits in a
+// c/c++ type. It traverses the type recursively, collecting occupied
+// bit intervals, and then computes the padding intervals.
+// If a byte only contains some padding bits, it gets intervals for only those
+// bits. This is the case for bit-fields.
+struct PaddingCalculator {
+ PaddingCalculator(const ASTContext &Ctx) : Ctx(Ctx) {}
+
+ void run(QualType Ty) {
+ OccuppiedIntervals.clear();
+ Stack.clear();
+
+ TySizeInBits = Ctx.getTypeSize(Ty);
+
+ Stack.push_back(Data{0, Ty, true});
+ while (!Stack.empty()) {
+ Data Current = Stack.back();
+ Stack.pop_back();
+ Visit(Current);
+ }
+ MergeOccuppiedIntervals();
+ }
+
+ llvm::SmallVector<ASTContext::BitInterval> GetPaddingIntervals() {
+ llvm::SmallVector<ASTContext::BitInterval> Results;
+ if (OccuppiedIntervals.size() == 1 &&
+ OccuppiedIntervals.front().First == 0 &&
+ OccuppiedIntervals.front().Last == TySizeInBits) {
+ return Results;
+ }
+ Results.reserve(OccuppiedIntervals.size() + 1);
+ uint64_t CurrentPos = 0;
+ for (const ASTContext::BitInterval &OccupiedInterval : OccuppiedIntervals)
{
+ if (OccupiedInterval.First > CurrentPos) {
+ Results.push_back(
+ ASTContext::BitInterval{CurrentPos, OccupiedInterval.First});
+ }
+ CurrentPos = OccupiedInterval.Last;
+ }
+ if (TySizeInBits > CurrentPos) {
+ Results.push_back(ASTContext::BitInterval{CurrentPos, TySizeInBits});
+ }
+ return Results;
+ }
+
+private:
+ struct Data {
+ uint64_t StartBitOffset;
+ QualType Ty;
+ bool VisitVirtualBase;
+ };
+
+ // Return the number of non padding bits of a scalar type.
+ //
+ // The property that we specifically care about here is whether the scalar
+ // type has padding bits, i.e. are there bits in the type which are not
+ // specified by the ABI.
+ //
+ // We currently don't care about this anywhere else in clang: layout cares
+ // about the ABI size, calling convention code cares about specific types,
+ // but nothing cares about padding specifically. And it's not something we
can
+ // easily query from LLVM due to the type system mismatches.
+ // DL.getTypeSizeInBits(convertTypeForLoadStore(T)) is probably close, but
the
+ // DataLayout methods aren't really designed for this usage.
+ //
+ // Therefore, it is better to explicitly list all the scalar types
+ // containing padding bits that we know of, namely, _BitInt(N) and x87 long
+ // double.
+ uint64_t getScalarOccupiedSizeInBits(QualType Ty) const {
+ if (const auto *BIT = Ty->getAs<BitIntType>())
+ return BIT->getNumBits();
+
+ if (const auto *BT = Ty->getAs<BuiltinType>()) {
+ if (BT->getKind() == BuiltinType::LongDouble &&
+ &Ctx.getTargetInfo().getLongDoubleFormat() ==
+ &llvm::APFloat::x87DoubleExtended())
+ return llvm::APFloat::getSizeInBits(
+ Ctx.getTargetInfo().getLongDoubleFormat());
+ }
+
+ return Ctx.getTypeSize(Ty);
+ }
+
+ void Visit(const Data &D) {
----------------
erichkeane wrote:
My guess is that because we're only using it from codegen that everything is
reasonably canonical by then? But yeah, I was a bit shocked when I was playing
with that yesterday. but added a bunch of `getCanonicalType` everywhere we
insert into `Data` now, so hopefully it won't be a problem.
https://github.com/llvm/llvm-project/pull/215823
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits