[clang] [clang][bytecode] Pass bitfield width directly to opcodes (PR #188423)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Mar 25 00:25:40 PDT 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Timm Baeder (tbaederr)
<details>
<summary>Changes</summary>
Pass a `FieldOffset` + `FieldBitWidth` pair instead of a `Record::Field` pointer.
---
Full diff: https://github.com/llvm/llvm-project/pull/188423.diff
4 Files Affected:
- (modified) clang/lib/AST/ByteCode/Compiler.cpp (+9-6)
- (modified) clang/lib/AST/ByteCode/Interp.h (+16-18)
- (modified) clang/lib/AST/ByteCode/Opcodes.td (+3-11)
- (modified) clang/lib/AST/ByteCode/Record.h (+4)
``````````diff
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index 642a59cf75642..941b33e4c314a 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 eb41021bcf7cf..c6d59c3af1154 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -1647,9 +1647,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))
@@ -1658,15 +1658,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))
@@ -1675,7 +1674,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;
@@ -1716,8 +1715,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))
@@ -1725,9 +1724,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())
@@ -1739,16 +1738,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))
@@ -1756,9 +1754,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())
@@ -1770,7 +1768,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 da3b850945499..0cf75c3ed4bef 100644
--- a/clang/lib/AST/ByteCode/Opcodes.td
+++ b/clang/lib/AST/ByteCode/Opcodes.td
@@ -414,7 +414,8 @@ class AccessOpcode : Opcode {
class BitFieldOpcode : Opcode {
let Types = [IntegralTypeClass];
- let Args = [ArgRecordField];
+ // FieldOffset, FieldBitWidth
+ let Args = [ArgUint32, ArgUint32];
let HasGroup = 1;
}
@@ -482,16 +483,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) {}
``````````
</details>
https://github.com/llvm/llvm-project/pull/188423
More information about the cfe-commits
mailing list