-
Notifications
You must be signed in to change notification settings - Fork 14.4k
[CIR] Upstream get_bitfield operation to load bit-field members from structs #145971
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-clangir @llvm/pr-subscribers-clang Author: None (Andres-Salamanca) ChangesThis PR adds support for retrieving a bitfield member. It obtains the member in which the bitfield is packed but does not emit the load operation, as the address will be computed later using the get_bitfield operation. Full diff: https://github.com/llvm/llvm-project/pull/145971.diff 5 Files Affected:
diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h
index 9e8944d1114b8..e136d73daac89 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -200,6 +200,7 @@ struct MissingFeatures {
static bool fastMathFlags() { return false; }
static bool fpConstraints() { return false; }
static bool generateDebugInfo() { return false; }
+ static bool getBitfieldOp() { return false; }
static bool hip() { return false; }
static bool implicitConstructorArgs() { return false; }
static bool incrementProfileCounter() { return false; }
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index 5c6604d784156..a3d24e92c701a 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -326,13 +326,47 @@ mlir::Value CIRGenFunction::emitStoreThroughBitfieldLValue(RValue src,
return {};
}
+Address CIRGenFunction::getAddrOfBitFieldStorage(LValue base,
+ const FieldDecl *field,
+ mlir::Type fieldType,
+ unsigned index) {
+ if (index == 0)
+ return base.getAddress();
+ mlir::Location loc = getLoc(field->getLocation());
+ cir::PointerType fieldPtr = cir::PointerType::get(fieldType);
+ cir::GetMemberOp sea = getBuilder().createGetMember(
+ loc, fieldPtr, base.getPointer(), field->getName(), index);
+ return Address(sea, CharUnits::One());
+}
+
+LValue CIRGenFunction::emitLValueForBitField(LValue base,
+ const FieldDecl *field) {
+ LValueBaseInfo baseInfo = base.getBaseInfo();
+ const CIRGenRecordLayout &layout =
+ cgm.getTypes().getCIRGenRecordLayout(field->getParent());
+ const CIRGenBitFieldInfo &info = layout.getBitFieldInfo(field);
+ assert(!cir::MissingFeatures::armComputeVolatileBitfields());
+ unsigned idx = layout.getCIRFieldNo(field);
+
+ Address addr = getAddrOfBitFieldStorage(base, field, info.storageType, idx);
+
+ mlir::Location loc = getLoc(field->getLocation());
+ if (addr.getElementType() != info.storageType)
+ addr = builder.createElementBitCast(loc, addr, info.storageType);
+
+ QualType fieldType =
+ field->getType().withCVRQualifiers(base.getVRQualifiers());
+ // TODO(cir): Support TBAA for bit fields.
+ assert(!cir::MissingFeatures::opTBAA());
+ LValueBaseInfo fieldBaseInfo(baseInfo.getAlignmentSource());
+ return LValue::makeBitfield(addr, info, fieldType, fieldBaseInfo);
+}
+
LValue CIRGenFunction::emitLValueForField(LValue base, const FieldDecl *field) {
LValueBaseInfo baseInfo = base.getBaseInfo();
- if (field->isBitField()) {
- cgm.errorNYI(field->getSourceRange(), "emitLValueForField: bitfield");
- return LValue();
- }
+ if (field->isBitField())
+ return emitLValueForBitField(base, field);
QualType fieldType = field->getType();
const RecordDecl *rec = field->getParent();
@@ -460,6 +494,11 @@ RValue CIRGenFunction::emitLoadOfLValue(LValue lv, SourceLocation loc) {
assert(!lv.getType()->isFunctionType());
assert(!(lv.getType()->isConstantMatrixType()) && "not implemented");
+ if (lv.isBitField()) {
+ assert(!cir::MissingFeatures::getBitfieldOp());
+ return RValue::getIgnored();
+ }
+
if (lv.isSimple())
return RValue::get(emitLoadOfScalar(lv, loc));
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index 2e54243f18cff..5139bc8249b3d 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -550,6 +550,9 @@ class CIRGenFunction : public CIRGenTypeCache {
return it->second;
}
+ Address getAddrOfBitFieldStorage(LValue base, const clang::FieldDecl *field,
+ mlir::Type fieldType, unsigned index);
+
/// Load the value for 'this'. This function is only valid while generating
/// code for an C++ member function.
/// FIXME(cir): this should return a mlir::Value!
@@ -964,6 +967,7 @@ class CIRGenFunction : public CIRGenTypeCache {
/// of the expression.
/// FIXME: document this function better.
LValue emitLValue(const clang::Expr *e);
+ LValue emitLValueForBitField(LValue base, const FieldDecl *field);
LValue emitLValueForField(LValue base, const clang::FieldDecl *field);
/// Like emitLValueForField, excpet that if the Field is a reference, this
diff --git a/clang/lib/CIR/CodeGen/CIRGenValue.h b/clang/lib/CIR/CodeGen/CIRGenValue.h
index a5a457ddafa9c..2d6bdb921c9fa 100644
--- a/clang/lib/CIR/CodeGen/CIRGenValue.h
+++ b/clang/lib/CIR/CodeGen/CIRGenValue.h
@@ -19,6 +19,7 @@
#include "clang/AST/CharUnits.h"
#include "clang/AST/Type.h"
+#include "CIRGenRecordLayout.h"
#include "mlir/IR/Value.h"
#include "clang/CIR/MissingFeatures.h"
@@ -162,6 +163,7 @@ class LValue {
mlir::Value vectorIdx; // Index for vector subscript
mlir::Type elementType;
LValueBaseInfo baseInfo;
+ const CIRGenBitFieldInfo *bitFieldInfo{nullptr};
void initialize(clang::QualType type, clang::Qualifiers quals,
clang::CharUnits alignment, LValueBaseInfo baseInfo) {
@@ -245,6 +247,23 @@ class LValue {
r.initialize(t, t.getQualifiers(), vecAddress.getAlignment(), baseInfo);
return r;
}
+
+ /// Create a new object to represent a bit-field access.
+ ///
+ /// \param Addr - The base address of the bit-field sequence this
+ /// bit-field refers to.
+ /// \param Info - The information describing how to perform the bit-field
+ /// access.
+ static LValue makeBitfield(Address addr, const CIRGenBitFieldInfo &info,
+ clang::QualType type, LValueBaseInfo baseInfo) {
+ LValue r;
+ r.lvType = BitField;
+ r.v = addr.getPointer();
+ r.elementType = addr.getElementType();
+ r.bitFieldInfo = &info;
+ r.initialize(type, type.getQualifiers(), addr.getAlignment(), baseInfo);
+ return r;
+ }
};
/// An aggregate value slot.
diff --git a/clang/test/CIR/CodeGen/bitfields.c b/clang/test/CIR/CodeGen/bitfields.c
index ff5c6bc1787b4..4cc1fc69ecc5a 100644
--- a/clang/test/CIR/CodeGen/bitfields.c
+++ b/clang/test/CIR/CodeGen/bitfields.c
@@ -76,3 +76,11 @@ void def() {
T t;
U u;
}
+
+// CIR: cir.func {{.*@load_field}}
+// CIR: [[TMP0:%.*]] = cir.alloca !cir.ptr<!rec_S>, !cir.ptr<!cir.ptr<!rec_S>>, ["s", init]
+// CIR: [[TMP1:%.*]] = cir.load{{.*}} [[TMP0]] : !cir.ptr<!cir.ptr<!rec_S>>, !cir.ptr<!rec_S>
+// CIR: [[TMP2:%.*]] = cir.get_member %2[1] {name = "e"} : !cir.ptr<!rec_S> -> !cir.ptr<!u16i>
+int load_field(S* s) {
+ return s->e;
+}
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I appreciate the small change, but in this case I think it would be better to introduce get_bitfield together with this code, because the expected behavior without it is unclear and difficult to evaluate.
I initially split this out because I also need to introduce a BitfieldInfoAttr, and combining everything in one patch would make it quite long. That said, I was already working on this in another branch, so I’ll go ahead and bring that code over and include get_bitfield here as well. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A couple of nits to docs, else this looks fine to me. I think @bcardosolopes should probably approve this though.
✅ With the latest revision this PR passed the C/C++ code formatter. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One minor suggestion and LGTM
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/206/builds/2699 Here is the relevant piece of the build log for the reference
|
This PR adds support for loading bit-field members from structs using the
get_bitfield
operation.It enables retrieving the address of the bitfield-packed member but does not yet support volatile bitfields this will be addressed in a future PR.