[cfe-commits] r166892 - in /cfe/trunk/lib/CodeGen: CGBlocks.cpp CGObjCGNU.cpp CGObjCMac.cpp CGObjCRuntime.h

Fariborz Jahanian fjahanian at apple.com
Sat Oct 27 14:10:38 PDT 2012


Author: fjahanian
Date: Sat Oct 27 16:10:38 2012
New Revision: 166892

URL: http://llvm.org/viewvc/llvm-project?rev=166892&view=rev
Log:
objective-C arc/mrr: Patch for the new block variable layout meta-data.
It is currently off (so no tests). This is wip.

Modified:
    cfe/trunk/lib/CodeGen/CGBlocks.cpp
    cfe/trunk/lib/CodeGen/CGObjCGNU.cpp
    cfe/trunk/lib/CodeGen/CGObjCMac.cpp
    cfe/trunk/lib/CodeGen/CGObjCRuntime.h

Modified: cfe/trunk/lib/CodeGen/CGBlocks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBlocks.cpp?rev=166892&r1=166891&r2=166892&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGBlocks.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGBlocks.cpp Sat Oct 27 16:10:38 2012
@@ -103,8 +103,12 @@
                           CGM.GetAddrOfConstantCString(typeAtEncoding), i8p));
   
   // GC layout.
-  if (C.getLangOpts().ObjC1)
-    elements.push_back(CGM.getObjCRuntime().BuildGCBlockLayout(CGM, blockInfo));
+  if (C.getLangOpts().ObjC1) {
+    if (CGM.getLangOpts().getGC() != LangOptions::NonGC)
+      elements.push_back(CGM.getObjCRuntime().BuildGCBlockLayout(CGM, blockInfo));
+    else
+      elements.push_back(CGM.getObjCRuntime().BuildRCBlockLayout(CGM, blockInfo));
+  }
   else
     elements.push_back(llvm::Constant::getNullValue(i8p));
 

Modified: cfe/trunk/lib/CodeGen/CGObjCGNU.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCGNU.cpp?rev=166892&r1=166891&r2=166892&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCGNU.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCGNU.cpp Sat Oct 27 16:10:38 2012
@@ -533,7 +533,10 @@
                                              const CGBlockInfo &blockInfo) {
     return NULLPtr;
   }
-  
+  virtual llvm::Constant *BuildRCBlockLayout(CodeGenModule &CGM,
+                                             const CGBlockInfo &blockInfo) {
+    return NULLPtr;
+  }
   virtual llvm::GlobalVariable *GetClassGlobal(const std::string &Name) {
     return 0;
   }

Modified: cfe/trunk/lib/CodeGen/CGObjCMac.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCMac.cpp?rev=166892&r1=166891&r2=166892&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCMac.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCMac.cpp Sat Oct 27 16:10:38 2012
@@ -811,9 +811,10 @@
   public:
     enum BLOCK_LAYOUT_OPCODE opcode;
     unsigned block_var_bytepos;
+    unsigned block_var_size;
     RUN_SKIP(enum BLOCK_LAYOUT_OPCODE Opcode = BLOCK_LAYOUT_OPERATOR,
-             unsigned BytePos = 0)
-    : opcode(Opcode), block_var_bytepos(BytePos) {}
+             unsigned BytePos = 0, unsigned Size = 0)
+    : opcode(Opcode), block_var_bytepos(BytePos),  block_var_size(Size) {}
     
     // Allow sorting based on byte pos.
     bool operator<(const RUN_SKIP &b) const {
@@ -1030,6 +1031,8 @@
   virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD)=0;
   virtual llvm::Constant *BuildGCBlockLayout(CodeGen::CodeGenModule &CGM,
                                              const CGBlockInfo &blockInfo);
+  virtual llvm::Constant *BuildRCBlockLayout(CodeGen::CodeGenModule &CGM,
+                                             const CGBlockInfo &blockInfo);
   
 };
 
@@ -1858,8 +1861,8 @@
 
 llvm::Constant *CGObjCCommonMac::BuildGCBlockLayout(CodeGenModule &CGM,
                                                 const CGBlockInfo &blockInfo) {
+  
   llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
-
   if (CGM.getLangOpts().getGC() == LangOptions::NonGC &&
       !CGM.getLangOpts().ObjCAutoRefCount)
     return nullPtr;
@@ -1943,6 +1946,164 @@
   return C;
 }
 
+llvm::Constant *CGObjCCommonMac::BuildRCBlockLayout(CodeGenModule &CGM,
+                                                    const CGBlockInfo &blockInfo) {
+  // FIXME. Temporary call the GC layout routine.
+  return BuildGCBlockLayout(CGM, blockInfo);
+  
+  assert(CGM.getLangOpts().getGC() == LangOptions::NonGC);
+  
+  llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
+  
+  RunSkipBlockVars.clear();
+  // bool hasUnion = false;
+  unsigned WordSizeInBits = CGM.getContext().getTargetInfo().getPointerWidth(0);
+  unsigned ByteSizeInBits = CGM.getContext().getTargetInfo().getCharWidth();
+  unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits;
+  
+  const BlockDecl *blockDecl = blockInfo.getBlockDecl();
+  
+  // Calculate the basic layout of the block structure.
+  const llvm::StructLayout *layout =
+  CGM.getDataLayout().getStructLayout(blockInfo.StructureType);
+  
+  // Ignore the optional 'this' capture: C++ objects are not assumed
+  // to be GC'ed.
+  
+  // Walk the captured variables.
+  for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(),
+       ce = blockDecl->capture_end(); ci != ce; ++ci) {
+    const VarDecl *variable = ci->getVariable();
+    QualType type = variable->getType();
+    
+    const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
+    
+    // Ignore constant captures.
+    if (capture.isConstant()) continue;
+    
+    uint64_t fieldOffset = layout->getElementOffset(capture.getIndex());
+    
+    // __block variables are passed by their descriptor address.
+    if (ci->isByRef()) {
+      RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_BYREF, fieldOffset,
+                                          WordSizeInBytes));
+      continue;
+    }
+    
+    assert(!type->isArrayType() && "array variable should not be caught");
+    assert(!type->getAs<RecordType>() &&
+           "BuildRCBlockLayout - captured records NYI");
+    
+    unsigned fieldSize = CGM.getContext().getTypeSize(type);
+    
+    if (type.getObjCLifetime() == Qualifiers::OCL_Strong)
+      RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_STRONG, fieldOffset,
+                                          WordSizeInBytes));
+    else if (type.getObjCLifetime() == Qualifiers::OCL_Weak)
+      RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_WEAK, fieldOffset,
+                                   WordSizeInBytes));
+    else if (type.getObjCLifetime() == Qualifiers::OCL_ExplicitNone)
+      RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_UNRETAINED, fieldOffset,
+                                   WordSizeInBytes));
+    else
+      RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_NON_OBJECT_BYTES, fieldOffset,
+                                   fieldSize/ByteSizeInBits));
+  }
+  
+  if (RunSkipBlockVars.empty())
+    return nullPtr;
+  
+  // Sort on byte position; captures might not be allocated in order,
+  // and unions can do funny things.
+  llvm::array_pod_sort(RunSkipBlockVars.begin(), RunSkipBlockVars.end());
+  std::string Layout;
+
+  unsigned size = RunSkipBlockVars.size();
+  unsigned int shift = (WordSizeInBytes == 8) ? 3 : 2;
+  unsigned int mask = (WordSizeInBytes == 8) ? 0x7 : 0x3;
+  for (unsigned i = 0; i < size; i++) {
+    enum BLOCK_LAYOUT_OPCODE opcode = RunSkipBlockVars[i].opcode;
+    unsigned start_byte_pos = RunSkipBlockVars[i].block_var_bytepos;
+    unsigned end_byte_pos = start_byte_pos;
+    unsigned j = i+1;
+    while (j < size) {
+      if (opcode == RunSkipBlockVars[j].opcode) {
+        end_byte_pos = RunSkipBlockVars[j++].block_var_bytepos;
+        i++;
+      }
+      else
+        break;
+    }
+    unsigned size_in_bytes =
+      end_byte_pos - start_byte_pos + RunSkipBlockVars[j-1].block_var_size;
+    unsigned residue_in_bytes = 0;
+    if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES) {
+      residue_in_bytes = size_in_bytes & mask;
+      size_in_bytes -= residue_in_bytes;
+      opcode = BLOCK_LAYOUT_NON_OBJECT_WORDS;
+    }
+
+    unsigned size_in_words = size_in_bytes >> shift;
+    while (size_in_words >= 16) {
+      // Note that value in imm. is one less that the actual
+      // value. So, 0xff means 16 words follow!
+      unsigned char inst = (opcode << 4) | 0xff;
+      Layout += inst;
+      size_in_words -= 16;
+    }
+    if (size_in_words > 0) {
+      // Note that value in imm. is one less that the actual
+      // value. So, we subtract 1 away!
+      unsigned char inst = (opcode << 4) | (size_in_words-1);
+      Layout += inst;
+    }
+    if (residue_in_bytes > 0) {
+      unsigned char inst = (BLOCK_LAYOUT_NON_OBJECT_BYTES << 4) | residue_in_bytes;
+      Layout += inst;
+    }
+  }
+  if (CGM.getLangOpts().ObjCGCBitmapPrint) {
+    printf("\n block variable layout: ");
+    for (unsigned i = 0, e = Layout.size(); i != e; i++) {
+      unsigned char inst = Layout[i];
+      enum BLOCK_LAYOUT_OPCODE opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
+      unsigned delta = 1;
+      switch (opcode) {
+        case BLOCK_LAYOUT_OPERATOR:
+          printf("BL_OPERATOR:");
+          break;
+        case BLOCK_LAYOUT_NON_OBJECT_BYTES:
+          printf("BL_NON_OBJECT_BYTES:");
+          delta = 0;
+          break;
+        case BLOCK_LAYOUT_NON_OBJECT_WORDS:
+          printf("BL_NON_OBJECT_WORD:");
+          break;
+        case BLOCK_LAYOUT_STRONG:
+          printf("BL_STRONG:");
+          break;
+        case BLOCK_LAYOUT_BYREF:
+          printf("BL_BYREF:");
+          break;
+        case BLOCK_LAYOUT_WEAK:
+          printf("BL_WEAK:");
+          break;
+        case BLOCK_LAYOUT_UNRETAINED:
+          printf("BL_UNRETAINE:");
+          break;
+      } 
+      // Actual value of word count is one more that what is in the imm.
+      // field of the instruction
+      printf("%d", (inst & 0xf) + delta); 
+      if (i < e-1)
+        printf(", ");
+      else
+        printf("\n");
+    }
+  }
+  return nullPtr;
+}
+
 llvm::Value *CGObjCMac::GenerateProtocolRef(CGBuilderTy &Builder,
                                             const ObjCProtocolDecl *PD) {
   // FIXME: I don't understand why gcc generates this, or where it is

Modified: cfe/trunk/lib/CodeGen/CGObjCRuntime.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCRuntime.h?rev=166892&r1=166891&r2=166892&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCRuntime.h (original)
+++ cfe/trunk/lib/CodeGen/CGObjCRuntime.h Sat Oct 27 16:10:38 2012
@@ -261,6 +261,8 @@
                                         llvm::Value *Size) = 0;
   virtual llvm::Constant *BuildGCBlockLayout(CodeGen::CodeGenModule &CGM,
                                   const CodeGen::CGBlockInfo &blockInfo) = 0;
+  virtual llvm::Constant *BuildRCBlockLayout(CodeGen::CodeGenModule &CGM,
+                                  const CodeGen::CGBlockInfo &blockInfo) = 0;
   virtual llvm::GlobalVariable *GetClassGlobal(const std::string &Name) = 0;
 
   struct MessageSendInfo {





More information about the cfe-commits mailing list