[cfe-commits] r101178 - in /cfe/trunk/lib/CodeGen: CGObjCMac.cpp CGRecordLayout.h CGRecordLayoutBuilder.cpp
Daniel Dunbar
daniel at zuster.org
Tue Apr 13 13:58:56 PDT 2010
Author: ddunbar
Date: Tue Apr 13 15:58:55 2010
New Revision: 101178
URL: http://llvm.org/viewvc/llvm-project?rev=101178&view=rev
Log:
IRgen: Enhance CGBitFieldInfo with enough information to fully describe the "policy" with which a bit-field should be accessed.
- For now, these policies are computed to match the current IRgen strategy, although the new information isn't being used yet (except in -fdump-record-layouts).
- Design comments appreciated.
Modified:
cfe/trunk/lib/CodeGen/CGObjCMac.cpp
cfe/trunk/lib/CodeGen/CGRecordLayout.h
cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp
Modified: cfe/trunk/lib/CodeGen/CGObjCMac.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCMac.cpp?rev=101178&r1=101177&r2=101178&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCMac.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCMac.cpp Tue Apr 13 15:58:55 2010
@@ -129,6 +129,17 @@
new (CGF.CGM.getContext()) CGBitFieldInfo(
LTy, FieldNo, BitOffset, BitFieldSize, IvarTy->isSignedIntegerType());
+ // We always construct a single, possibly unaligned, access for this case.
+ Info->setNumComponents(1);
+ CGBitFieldInfo::AccessInfo &AI = Info->getComponent(0);
+ AI.FieldIndex = 0;
+ AI.FieldByteOffset = 0;
+ AI.FieldBitStart = BitOffset;
+ AI.AccessWidth = CGF.CGM.getContext().getTypeSize(IvarTy);
+ AI.AccessAlignment = 0;
+ AI.TargetBitOffset = 0;
+ AI.TargetBitWidth = BitFieldSize;
+
// FIXME: We need to set a very conservative alignment on this, or make sure
// that the runtime is doing the right thing.
return LValue::MakeBitfield(V, *Info, Quals.getCVRQualifiers());
Modified: cfe/trunk/lib/CodeGen/CGRecordLayout.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGRecordLayout.h?rev=101178&r1=101177&r2=101178&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGRecordLayout.h (original)
+++ cfe/trunk/lib/CodeGen/CGRecordLayout.h Tue Apr 13 15:58:55 2010
@@ -20,10 +20,74 @@
namespace clang {
namespace CodeGen {
-/// Helper object for describing how to generate the code for access to a
+/// \brief Helper object for describing how to generate the code for access to a
/// bit-field.
+///
+/// This structure is intended to describe the "policy" of how the bit-field
+/// should be accessed, which may be target, language, or ABI dependent.
class CGBitFieldInfo {
public:
+ /// Descriptor for a single component of a bit-field access. The entire
+ /// bit-field is constituted of a bitwise OR of all of the individual
+ /// components.
+ ///
+ /// Each component describes an accessed value, which is how the component
+ /// should be transferred to/from memory, and a target placement, which is how
+ /// that component fits into the constituted bit-field. The pseudo-IR for a
+ /// load is:
+ ///
+ /// %0 = gep %base, 0, FieldIndex
+ /// %1 = gep (i8*) %0, FieldByteOffset
+ /// %2 = (i(AccessWidth) *) %1
+ /// %3 = load %2, align AccessAlignment
+ /// %4 = shr %3, FieldBitStart
+ ///
+ /// and the composed bit-field is formed as the boolean OR of all accesses,
+ /// masked to TargetBitWidth bits and shifted to TargetBitOffset.
+ struct AccessInfo {
+ /// Offset of the field to load in the LLVM structure, if any.
+ unsigned FieldIndex;
+
+ /// Byte offset from the field address, if any. This should generally be
+ /// unused as the cleanest IR comes from having a well-constructed LLVM type
+ /// with proper GEP instructions, but sometimes its use is required, for
+ /// example if an access is intended to straddle an LLVM field boundary.
+ unsigned FieldByteOffset;
+
+ /// Bit offset in the accessed value to use. The width is implied by \see
+ /// TargetBitWidth.
+ unsigned FieldBitStart;
+
+ /// Bit width of the memory access to perform.
+ unsigned AccessWidth;
+
+ /// The alignment of the memory access, or 0 if the default alignment should
+ /// be used.
+ //
+ // FIXME: Remove use of 0 to encode default, instead have IRgen do the right
+ // thing when it generates the code, if avoiding align directives is
+ // desired.
+ unsigned AccessAlignment;
+
+ /// Offset for the target value.
+ unsigned TargetBitOffset;
+
+ /// Number of bits in the access that are destined for the bit-field.
+ unsigned TargetBitWidth;
+ };
+
+private:
+ /// The number of access components to use.
+ unsigned NumComponents;
+
+ /// The components to use to access the bit-field. We may need up to three
+ /// separate components to support up to i64 bit-field access (4 + 2 + 1 byte
+ /// accesses).
+ //
+ // FIXME: De-hardcode this, just allocate following the struct.
+ AccessInfo Components[3];
+
+public:
CGBitFieldInfo(const llvm::Type *FieldTy, unsigned FieldNo,
unsigned Start, unsigned Size, bool IsSigned)
: FieldTy(FieldTy), FieldNo(FieldNo),
@@ -36,6 +100,24 @@
unsigned Size;
bool IsSigned : 1;
+public:
+ bool isSigned() const { return IsSigned; }
+
+ unsigned getNumComponents() const { return NumComponents; }
+ void setNumComponents(unsigned Value) {
+ assert(Value < 4 && "Invalid number of components!");
+ NumComponents = Value;
+ }
+
+ const AccessInfo &getComponent(unsigned Index) const {
+ assert(Index < getNumComponents() && "Invalid access!");
+ return Components[Index];
+ }
+ AccessInfo &getComponent(unsigned Index) {
+ assert(Index < getNumComponents() && "Invalid access!");
+ return Components[Index];
+ }
+
void print(llvm::raw_ostream &OS) const;
void dump() const;
};
Modified: cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp?rev=101178&r1=101177&r2=101178&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp Tue Apr 13 15:58:55 2010
@@ -150,12 +150,45 @@
uint64_t FieldOffset,
uint64_t FieldSize) {
const llvm::Type *Ty = Types.ConvertTypeForMemRecursive(FD->getType());
- uint64_t TypeSizeInBits = Types.getTargetData().getTypeAllocSize(Ty) * 8;
+ uint64_t TypeSizeInBytes = Types.getTargetData().getTypeAllocSize(Ty);
+ uint64_t TypeSizeInBits = TypeSizeInBytes * 8;
bool IsSigned = FD->getType()->isSignedIntegerType();
CGBitFieldInfo BFI(Ty, FieldOffset / TypeSizeInBits,
FieldOffset % TypeSizeInBits, FieldSize, IsSigned);
+ // The current policy is to always access the bit-field using the source type
+ // of the bit-field. With the C bit-field rules, this implies that we always
+ // use either one or two accesses, and two accesses can only occur with a
+ // packed structure when the bit-field straddles an alignment boundary.
+ unsigned LowBits = std::min(FieldSize, TypeSizeInBits - BFI.Start);
+ bool NeedsHighAccess = LowBits != FieldSize;
+ BFI.setNumComponents(1 + NeedsHighAccess);
+
+ // FIXME: This access policy is probably wrong on big-endian systems.
+ CGBitFieldInfo::AccessInfo &LowAccess = BFI.getComponent(0);
+ LowAccess.FieldIndex = 0;
+ LowAccess.FieldByteOffset =
+ TypeSizeInBytes * ((FieldOffset / 8) / TypeSizeInBytes);
+ LowAccess.FieldBitStart = BFI.Start;
+ LowAccess.AccessWidth = TypeSizeInBits;
+ // FIXME: This might be wrong!
+ LowAccess.AccessAlignment = 0;
+ LowAccess.TargetBitOffset = 0;
+ LowAccess.TargetBitWidth = LowBits;
+
+ if (NeedsHighAccess) {
+ CGBitFieldInfo::AccessInfo &HighAccess = BFI.getComponent(1);
+ HighAccess.FieldIndex = 0;
+ HighAccess.FieldByteOffset = LowAccess.FieldByteOffset + TypeSizeInBytes;
+ HighAccess.FieldBitStart = 0;
+ HighAccess.AccessWidth = TypeSizeInBits;
+ // FIXME: This might be wrong!
+ HighAccess.AccessAlignment = 0;
+ HighAccess.TargetBitOffset = LowBits;
+ HighAccess.TargetBitWidth = FieldSize - LowBits;
+ }
+
return BFI;
}
@@ -500,8 +533,13 @@
for (unsigned i = 0, e = Builder.LLVMBitFields.size(); i != e; ++i)
RL->BitFields.insert(Builder.LLVMBitFields[i]);
- if (getContext().getLangOptions().DumpRecordLayouts)
+ if (getContext().getLangOptions().DumpRecordLayouts) {
+ llvm::errs() << "\n*** Dumping Record Layout\n";
+ llvm::errs() << "Record: ";
+ D->dump();
+ llvm::errs() << "\nLayout: ";
RL->dump();
+ }
return RL;
}
@@ -514,7 +552,7 @@
for (llvm::DenseMap<const FieldDecl*, CGBitFieldInfo>::const_iterator
it = BitFields.begin(), ie = BitFields.end();
it != ie; ++it) {
- OS << " ";
+ OS.indent(4);
it->second.print(OS);
OS << "\n";
}
@@ -531,8 +569,30 @@
OS << " FieldNo:" << FieldNo;
OS << " Start:" << Start;
OS << " Size:" << Size;
- OS << " IsSigned:" << IsSigned;
- OS << ">";
+ OS << " IsSigned:" << IsSigned << "\n";
+
+ OS.indent(4 + strlen("<CGBitFieldInfo"));
+ OS << " NumComponents:" << getNumComponents();
+ OS << " Components: [";
+ if (getNumComponents()) {
+ OS << "\n";
+ for (unsigned i = 0, e = getNumComponents(); i != e; ++i) {
+ const AccessInfo &AI = getComponent(i);
+ OS.indent(8);
+ OS << "<AccessInfo"
+ << " FieldIndex:" << AI.FieldIndex
+ << " FieldByteOffset:" << AI.FieldByteOffset
+ << " FieldBitStart:" << AI.FieldBitStart
+ << " AccessWidth:" << AI.AccessWidth << "\n";
+ OS.indent(8 + strlen("<AccessInfo"));
+ OS << " AccessAlignment:" << AI.AccessAlignment
+ << " TargetBitOffset:" << AI.TargetBitOffset
+ << " TargetBitWidth:" << AI.TargetBitWidth
+ << ">\n";
+ }
+ OS.indent(4);
+ }
+ OS << "]>";
}
void CGBitFieldInfo::dump() const {
More information about the cfe-commits
mailing list