Put something sane in the DWARF offset field for bitfield ObjC ivars.
authorEli Friedman <eli.friedman@gmail.com>
Tue, 6 Nov 2012 23:40:48 +0000 (23:40 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Tue, 6 Nov 2012 23:40:48 +0000 (23:40 +0000)
This is useful because unnamed bitfields can have effects on the
offsets which are not otherwise reflected in the DWARF information.

<rdar://problem/12629719>

llvm-svn: 167503

clang/lib/CodeGen/CGDebugInfo.cpp
clang/lib/CodeGen/CGObjCRuntime.cpp
clang/lib/CodeGen/CGObjCRuntime.h
clang/test/CodeGenObjC/debug-info-ivars.m [new file with mode: 0644]

index 7dfaaa4..80fa09b 100644 (file)
@@ -15,6 +15,7 @@
 #include "CodeGenFunction.h"
 #include "CodeGenModule.h"
 #include "CGBlocks.h"
+#include "CGObjCRuntime.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/DeclFriend.h"
 #include "clang/AST/DeclObjC.h"
@@ -1412,12 +1413,21 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
       FieldAlign = CGM.getContext().getTypeAlign(FType);
     }
 
-    // We can't know the offset of our ivar in the structure if we're using
-    // the non-fragile abi and the debugger should ignore the value anyways.
-    // Call it the FieldNo+1 due to how debuggers use the information,
-    // e.g. negating the value when it needs a lookup in the dynamic table.
-    uint64_t FieldOffset = CGM.getLangOpts().ObjCRuntime.isNonFragile()
-                             ? FieldNo+1 : RL.getFieldOffset(FieldNo);
+    uint64_t FieldOffset;
+    if (CGM.getLangOpts().ObjCRuntime.isNonFragile()) {
+      // We don't know the runtime offset of an ivar if we're using the
+      // non-fragile ABI.  For bitfields, use the bit offset into the first
+      // byte of storage of the bitfield.  For other fields, use zero.
+      if (Field->isBitField()) {
+        FieldOffset = CGM.getObjCRuntime().ComputeBitfieldBitOffset(
+            CGM, ID, Field);
+        FieldOffset %= CGM.getContext().getCharWidth();
+      } else {
+        FieldOffset = 0;
+      }
+    } else {
+      FieldOffset = RL.getFieldOffset(FieldNo);
+    }
 
     unsigned Flags = 0;
     if (Field->getAccessControl() == ObjCIvarDecl::Protected)
index 9aa6837..6932dd7 100644 (file)
@@ -78,6 +78,13 @@ uint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM,
     CGM.getContext().getCharWidth();
 }
 
+unsigned CGObjCRuntime::ComputeBitfieldBitOffset(
+    CodeGen::CodeGenModule &CGM,
+    const ObjCInterfaceDecl *ID,
+    const ObjCIvarDecl *Ivar) {
+  return LookupFieldBitOffset(CGM, ID, ID->getImplementation(), Ivar);
+}
+
 LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF,
                                                const ObjCInterfaceDecl *OID,
                                                llvm::Value *BaseValue,
index bc6589d..3e77875 100644 (file)
@@ -277,6 +277,12 @@ public:
   MessageSendInfo getMessageSendInfo(const ObjCMethodDecl *method,
                                      QualType resultType,
                                      CallArgList &callArgs);
+
+  // FIXME: This probably shouldn't be here, but the code to compute
+  // it is here.
+  unsigned ComputeBitfieldBitOffset(CodeGen::CodeGenModule &CGM,
+                                    const ObjCInterfaceDecl *ID,
+                                    const ObjCIvarDecl *Ivar);
 };
 
 /// Creates an instance of an Objective-C runtime class.
diff --git a/clang/test/CodeGenObjC/debug-info-ivars.m b/clang/test/CodeGenObjC/debug-info-ivars.m
new file mode 100644 (file)
index 0000000..24705e1
--- /dev/null
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -g %s -o - | FileCheck %s
+
+__attribute((objc_root_class)) @interface NSObject {
+       id isa;
+}
+@end
+
+@interface BaseClass : NSObject
+{
+    int i;
+    unsigned flag_1 : 9;
+    unsigned flag_2 : 9;
+               unsigned : 1;
+               unsigned flag_3 : 9;
+}
+@end
+
+@implementation BaseClass
+@end
+
+// CHECK: metadata !{i32 786445, metadata !{{[0-9]*}}, metadata !"i", metadata !{{[0-9]*}}, i32 10, i64 32, i64 32, i64 0, i32 2, metadata !{{[0-9]*}}, null} ; [ DW_TAG_member ] [i] [line 10, size 32, align 32, offset 0] [protected] [from int]
+// CHECK: metadata !{i32 786445, metadata !{{[0-9]*}}, metadata !"flag_1", metadata !{{[0-9]*}}, i32 11, i64 9, i64 32, i64 0, i32 2, metadata !{{[0-9]*}}, null} ; [ DW_TAG_member ] [flag_1] [line 11, size 9, align 32, offset 0] [protected] [from unsigned int]
+// CHECK: metadata !{i32 786445, metadata !{{[0-9]*}}, metadata !"flag_2", metadata !{{[0-9]*}}, i32 12, i64 9, i64 32, i64 1, i32 2, metadata !{{[0-9]*}}, null} ; [ DW_TAG_member ] [flag_2] [line 12, size 9, align 32, offset 1] [protected] [from unsigned int]
+// CHECK: metadata !{i32 786445, metadata !{{[0-9]*}}, metadata !"flag_3", metadata !{{[0-9]*}}, i32 14, i64 9, i64 32, i64 3, i32 2, metadata !{{[0-9]*}}, null} ; [ DW_TAG_member ] [flag_3] [line 14, size 9, align 32, offset 3] [protected] [from unsigned int]
\ No newline at end of file