[clang] 8a49af8 - [clang][bytecode] Pass bitfield width directly to opcodes (#188423)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Mar 26 22:56:07 PDT 2026
Author: Timm Baeder
Date: 2026-03-27T06:56:03+01:00
New Revision: 8a49af8752021bbabc6f76e657beaf56a4645624
URL: https://github.com/llvm/llvm-project/commit/8a49af8752021bbabc6f76e657beaf56a4645624
DIFF: https://github.com/llvm/llvm-project/commit/8a49af8752021bbabc6f76e657beaf56a4645624.diff
LOG: [clang][bytecode] Pass bitfield width directly to opcodes (#188423)
Pass a `FieldOffset` + `FieldBitWidth` pair instead of a `Record::Field`
pointer.
Added:
Modified:
clang/lib/AST/ByteCode/Compiler.cpp
clang/lib/AST/ByteCode/Interp.h
clang/lib/AST/ByteCode/Opcodes.td
clang/lib/AST/ByteCode/Record.h
Removed:
################################################################################
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index c38eb0fa93877..217ba3663edb0 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -2130,9 +2130,11 @@ bool Compiler<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
bool BitField = FieldToInit->isBitField();
if (BitField && Activate)
- return this->emitInitBitFieldActivate(T, FieldToInit, E);
+ return this->emitInitBitFieldActivate(T, FieldToInit->Offset,
+ FieldToInit->bitWidth(), E);
if (BitField)
- return this->emitInitBitField(T, FieldToInit, E);
+ return this->emitInitBitField(T, FieldToInit->Offset,
+ FieldToInit->bitWidth(), E);
if (Activate)
return this->emitInitFieldActivate(T, FieldToInit->Offset, E);
return this->emitInitField(T, FieldToInit->Offset, E);
@@ -5361,7 +5363,8 @@ bool Compiler<Emitter>::visitAPValueInitializer(const APValue &Val,
if (!this->visitAPValue(F, *PT, E))
return false;
if (RF->isBitField())
- return this->emitInitBitFieldActivate(*PT, RF, E);
+ return this->emitInitBitFieldActivate(*PT, RF->Offset, RF->bitWidth(),
+ E);
return this->emitInitFieldActivate(*PT, RF->Offset, E);
}
@@ -6669,9 +6672,9 @@ bool Compiler<Emitter>::compileConstructor(const CXXConstructorDecl *Ctor) {
if (!this->visit(InitExpr))
return false;
- bool BitField = F->isBitField();
- if (BitField)
- return this->emitInitThisBitField(*T, F, FieldOffset, InitExpr);
+ if (F->isBitField())
+ return this->emitInitThisBitField(*T, FieldOffset, F->bitWidth(),
+ InitExpr);
return this->emitInitThisField(*T, FieldOffset, InitExpr);
}
// Non-primitive case. Get a pointer to the field-to-initialize
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index 5b6d1bb18fff4..90dc88c1dbde7 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -1659,9 +1659,9 @@ bool InitThisFieldActivate(InterpState &S, CodePtr OpPC, uint32_t I) {
// FIXME: The Field pointer here is too much IMO and we could instead just
// pass an Offset + BitWidth pair.
template <PrimType Name, class T = typename PrimConv<Name>::T>
-bool InitThisBitField(InterpState &S, CodePtr OpPC, const Record::Field *F,
- uint32_t FieldOffset) {
- assert(F->isBitField());
+bool InitThisBitField(InterpState &S, CodePtr OpPC,
+ uint32_t FieldOffset, // const Record::Field *F,
+ uint32_t FieldBitWidth) {
if (S.checkingPotentialConstantExpression() && S.Current->getDepth() == 0)
return false;
if (!CheckThis(S, OpPC))
@@ -1670,15 +1670,14 @@ bool InitThisBitField(InterpState &S, CodePtr OpPC, const Record::Field *F,
const Pointer &Field = This.atField(FieldOffset);
assert(Field.canBeInitialized());
const auto &Value = S.Stk.pop<T>();
- Field.deref<T>() = Value.truncate(F->Decl->getBitWidthValue());
+ Field.deref<T>() = Value.truncate(FieldBitWidth);
Field.initialize();
return true;
}
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool InitThisBitFieldActivate(InterpState &S, CodePtr OpPC,
- const Record::Field *F, uint32_t FieldOffset) {
- assert(F->isBitField());
+ uint32_t FieldOffset, uint32_t FieldBitWidth) {
if (S.checkingPotentialConstantExpression() && S.Current->getDepth() == 0)
return false;
if (!CheckThis(S, OpPC))
@@ -1687,7 +1686,7 @@ bool InitThisBitFieldActivate(InterpState &S, CodePtr OpPC,
const Pointer &Field = This.atField(FieldOffset);
assert(Field.canBeInitialized());
const auto &Value = S.Stk.pop<T>();
- Field.deref<T>() = Value.truncate(F->Decl->getBitWidthValue());
+ Field.deref<T>() = Value.truncate(FieldBitWidth);
Field.initialize();
Field.activate();
return true;
@@ -1728,8 +1727,8 @@ bool InitFieldActivate(InterpState &S, CodePtr OpPC, uint32_t I) {
}
template <PrimType Name, class T = typename PrimConv<Name>::T>
-bool InitBitField(InterpState &S, CodePtr OpPC, const Record::Field *F) {
- assert(F->isBitField());
+bool InitBitField(InterpState &S, CodePtr OpPC, uint32_t FieldOffset,
+ uint32_t FieldBitWidth) {
const T &Value = S.Stk.pop<T>();
const Pointer &Ptr = S.Stk.peek<Pointer>();
if (!CheckRange(S, OpPC, Ptr, CSK_Field))
@@ -1737,9 +1736,9 @@ bool InitBitField(InterpState &S, CodePtr OpPC, const Record::Field *F) {
if (!CheckArray(S, OpPC, Ptr))
return false;
- const Pointer &Field = Ptr.atField(F->Offset);
+ const Pointer &Field = Ptr.atField(FieldOffset);
- unsigned BitWidth = std::min(F->Decl->getBitWidthValue(), Value.bitWidth());
+ unsigned BitWidth = std::min(FieldBitWidth, Value.bitWidth());
if constexpr (needsAlloc<T>()) {
T Result = S.allocAP<T>(Value.bitWidth());
if constexpr (T::isSigned())
@@ -1751,16 +1750,15 @@ bool InitBitField(InterpState &S, CodePtr OpPC, const Record::Field *F) {
Field.deref<T>() = Result;
} else {
- Field.deref<T>() = Value.truncate(F->Decl->getBitWidthValue());
+ Field.deref<T>() = Value.truncate(FieldBitWidth);
}
Field.initialize();
return true;
}
template <PrimType Name, class T = typename PrimConv<Name>::T>
-bool InitBitFieldActivate(InterpState &S, CodePtr OpPC,
- const Record::Field *F) {
- assert(F->isBitField());
+bool InitBitFieldActivate(InterpState &S, CodePtr OpPC, uint32_t FieldOffset,
+ uint32_t FieldBitWidth) {
const T &Value = S.Stk.pop<T>();
const Pointer &Ptr = S.Stk.peek<Pointer>();
if (!CheckRange(S, OpPC, Ptr, CSK_Field))
@@ -1768,9 +1766,9 @@ bool InitBitFieldActivate(InterpState &S, CodePtr OpPC,
if (!CheckArray(S, OpPC, Ptr))
return false;
- const Pointer &Field = Ptr.atField(F->Offset);
+ const Pointer &Field = Ptr.atField(FieldOffset);
- unsigned BitWidth = std::min(F->Decl->getBitWidthValue(), Value.bitWidth());
+ unsigned BitWidth = std::min(FieldBitWidth, Value.bitWidth());
if constexpr (needsAlloc<T>()) {
T Result = S.allocAP<T>(Value.bitWidth());
if constexpr (T::isSigned())
@@ -1782,7 +1780,7 @@ bool InitBitFieldActivate(InterpState &S, CodePtr OpPC,
Field.deref<T>() = Result;
} else {
- Field.deref<T>() = Value.truncate(F->Decl->getBitWidthValue());
+ Field.deref<T>() = Value.truncate(FieldBitWidth);
}
Field.activate();
Field.initialize();
diff --git a/clang/lib/AST/ByteCode/Opcodes.td b/clang/lib/AST/ByteCode/Opcodes.td
index 5fbd35950c0eb..5e4d0ab2a84af 100644
--- a/clang/lib/AST/ByteCode/Opcodes.td
+++ b/clang/lib/AST/ByteCode/Opcodes.td
@@ -417,7 +417,8 @@ class AccessOpcode : Opcode {
class BitFieldOpcode : Opcode {
let Types = [IntegralTypeClass];
- let Args = [ArgRecordField];
+ // FieldOffset, FieldBitWidth
+ let Args = [ArgUint32, ArgUint32];
let HasGroup = 1;
}
@@ -485,16 +486,7 @@ def SetThisField : AccessOpcode;
def InitThisField : AccessOpcode;
def InitThisFieldActivate : AccessOpcode;
// [Value] -> []
-def InitThisBitField : Opcode {
- let Types = [AluTypeClass];
- let Args = [ArgRecordField, ArgUint32];
- let HasGroup = 1;
-}
-def InitThisBitFieldActivate : Opcode {
- let Types = [AluTypeClass];
- let Args = [ArgRecordField, ArgUint32];
- let HasGroup = 1;
-}
+def InitThisBitField : BitFieldOpcode;
// [Pointer, Value] -> []
def InitField : AccessOpcode;
def InitFieldActivate : AccessOpcode;
diff --git a/clang/lib/AST/ByteCode/Record.h b/clang/lib/AST/ByteCode/Record.h
index e43f683364e26..c0c10f72ae3ee 100644
--- a/clang/lib/AST/ByteCode/Record.h
+++ b/clang/lib/AST/ByteCode/Record.h
@@ -32,6 +32,10 @@ class Record final {
bool isBitField() const { return Decl->isBitField(); }
bool isUnnamedBitField() const { return Decl->isUnnamedBitField(); }
+ unsigned bitWidth() const {
+ assert(isBitField());
+ return Decl->getBitWidthValue();
+ }
Field(const FieldDecl *D, const Descriptor *Desc, unsigned Offset)
: Decl(D), Desc(Desc), Offset(Offset) {}
More information about the cfe-commits
mailing list