[cfe-commits] r44540 - /cfe/trunk/Driver/RewriteTest.cpp

Fariborz Jahanian fjahanian at apple.com
Mon Dec 3 11:17:29 PST 2007


Author: fjahanian
Date: Mon Dec  3 13:17:29 2007
New Revision: 44540

URL: http://llvm.org/viewvc/llvm-project?rev=44540&view=rev
Log:
Added support for messagings which return a structure-value.
(Also fixed a regression caused by recent changes to synthesis of structs).

Modified:
    cfe/trunk/Driver/RewriteTest.cpp

Modified: cfe/trunk/Driver/RewriteTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/RewriteTest.cpp?rev=44540&r1=44539&r2=44540&view=diff

==============================================================================
--- cfe/trunk/Driver/RewriteTest.cpp (original)
+++ cfe/trunk/Driver/RewriteTest.cpp Mon Dec  3 13:17:29 2007
@@ -43,10 +43,12 @@
     
     FunctionDecl *MsgSendFunctionDecl;
     FunctionDecl *MsgSendSuperFunctionDecl;
+    FunctionDecl *MsgSendStretFunctionDecl;
+    FunctionDecl *MsgSendSuperStretFunctionDecl;
     FunctionDecl *GetClassFunctionDecl;
     FunctionDecl *SelGetUidFunctionDecl;
     FunctionDecl *CFStringFunctionDecl;
-    
+      
     // ObjC string constant support.
     FileVarDecl *ConstantStringClassReference;
     RecordDecl *NSStringRecord;
@@ -62,6 +64,8 @@
       SM = &Context->SourceMgr;
       MsgSendFunctionDecl = 0;
       MsgSendSuperFunctionDecl = 0;
+      MsgSendStretFunctionDecl = 0;
+      MsgSendSuperStretFunctionDecl = 0;
       GetClassFunctionDecl = 0;
       SelGetUidFunctionDecl = 0;
       CFStringFunctionDecl = 0;
@@ -85,6 +89,10 @@
                       "(struct objc_object *, struct objc_selector *, ...);\n"
                       "extern struct objc_object *objc_msgSendSuper"
                       "(struct objc_super *, struct objc_selector *, ...);\n"
+                      "extern struct objc_object *objc_msgSend_stret"
+                      "(struct objc_object *, struct objc_selector *, ...);\n"
+                      "extern struct objc_object *objc_msgSendSuper_stret"
+                      "(struct objc_super *, struct objc_selector *, ...);\n"
                       "extern struct objc_object *objc_getClass"
                       "(const char *);\n"
                       "extern void objc_exception_throw(struct objc_object *);\n"
@@ -140,6 +148,8 @@
                                            Expr **args, unsigned nargs);
     void SynthMsgSendFunctionDecl();
     void SynthMsgSendSuperFunctionDecl();
+    void SynthMsgSendStretFunctionDecl();
+    void SynthMsgSendSuperStretFunctionDecl();
     void SynthGetClassFunctionDecl();
     void SynthCFStringFunctionDecl();
       
@@ -1047,6 +1057,46 @@
                                               FunctionDecl::Extern, false, 0);
 }
 
+// SynthMsgSendStretFunctionDecl - id objc_msgSend_stret(id self, SEL op, ...);
+void RewriteTest::SynthMsgSendStretFunctionDecl() {
+  IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_stret");
+  llvm::SmallVector<QualType, 16> ArgTys;
+  QualType argT = Context->getObjcIdType();
+  assert(!argT.isNull() && "Can't find 'id' type");
+  ArgTys.push_back(argT);
+  argT = Context->getObjcSelType();
+  assert(!argT.isNull() && "Can't find 'SEL' type");
+  ArgTys.push_back(argT);
+  QualType msgSendType = Context->getFunctionType(Context->getObjcIdType(),
+                                                  &ArgTys[0], ArgTys.size(),
+                                                  true /*isVariadic*/);
+  MsgSendStretFunctionDecl = new FunctionDecl(SourceLocation(), 
+                                         msgSendIdent, msgSendType,
+                                         FunctionDecl::Extern, false, 0);
+}
+
+// SynthMsgSendSuperStretFunctionDecl - 
+// id objc_msgSendSuper_stret(struct objc_super *, SEL op, ...);
+void RewriteTest::SynthMsgSendSuperStretFunctionDecl() {
+  IdentifierInfo *msgSendIdent = 
+    &Context->Idents.get("objc_msgSendSuper_stret");
+  llvm::SmallVector<QualType, 16> ArgTys;
+  RecordDecl *RD = new RecordDecl(Decl::Struct, SourceLocation(),
+                                  &Context->Idents.get("objc_super"), 0);
+  QualType argT = Context->getPointerType(Context->getTagDeclType(RD));
+  assert(!argT.isNull() && "Can't build 'struct objc_super *' type");
+  ArgTys.push_back(argT);
+  argT = Context->getObjcSelType();
+  assert(!argT.isNull() && "Can't find 'SEL' type");
+  ArgTys.push_back(argT);
+  QualType msgSendType = Context->getFunctionType(Context->getObjcIdType(),
+                                                  &ArgTys[0], ArgTys.size(),
+                                                  true /*isVariadic*/);
+  MsgSendSuperStretFunctionDecl = new FunctionDecl(SourceLocation(), 
+                                              msgSendIdent, msgSendType,
+                                              FunctionDecl::Extern, false, 0);
+}
+
 // SynthGetClassFunctionDecl - id objc_getClass(const char *name);
 void RewriteTest::SynthGetClassFunctionDecl() {
   IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getClass");
@@ -1181,11 +1231,23 @@
     SynthMsgSendFunctionDecl();
   if (!MsgSendSuperFunctionDecl)
     SynthMsgSendSuperFunctionDecl();
+  if (!MsgSendStretFunctionDecl)
+    SynthMsgSendStretFunctionDecl();
+  if (!MsgSendSuperStretFunctionDecl)
+    SynthMsgSendSuperStretFunctionDecl();
   if (!GetClassFunctionDecl)
     SynthGetClassFunctionDecl();
-
+  
   // default to objc_msgSend().
-  FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl; 
+  FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl;
+  // May need to use objc_msgSend_stret() as well.
+  FunctionDecl *MsgSendStretFlavor = 0;
+  if (ObjcMethodDecl *mDecl = Exp->getMethodDecl()) {
+    QualType resultType = mDecl->getResultType();
+    if (resultType.getCanonicalType()->isStructureType() 
+        || resultType.getCanonicalType()->isUnionType())
+      MsgSendStretFlavor = MsgSendStretFunctionDecl;
+  }
   
   // Synthesize a call to objc_msgSend().
   llvm::SmallVector<Expr*, 8> MsgExprs;
@@ -1207,6 +1269,8 @@
 
     if (ObjcInterfaceDecl *ID = isSuperReceiver(recExpr)) {
       MsgSendFlavor = MsgSendSuperFunctionDecl;
+      if (MsgSendStretFlavor)
+        MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;
       assert(MsgSendFlavor && "MsgSendFlavor is NULL!");
       
       llvm::SmallVector<Expr*, 4> InitExprs;
@@ -1288,7 +1352,8 @@
   QualType msgSendType = MsgSendFlavor->getType();
   
   // Create a reference to the objc_msgSend() declaration.
-  DeclRefExpr *DRE = new DeclRefExpr(MsgSendFlavor, msgSendType, SourceLocation());
+  DeclRefExpr *DRE = new DeclRefExpr(MsgSendFlavor, msgSendType, 
+                                     SourceLocation());
 
   // Need to cast objc_msgSend to "void *" (to workaround a GCC bandaid). 
   // If we don't do this cast, we get the following bizarre warning/note:
@@ -1310,6 +1375,59 @@
   const FunctionType *FT = msgSendType->getAsFunctionType();
   CallExpr *CE = new CallExpr(PE, &MsgExprs[0], MsgExprs.size(), 
                               FT->getResultType(), SourceLocation());
+  if (MsgSendStretFlavor) {
+    // We have the method which returns a struct/union. Must also generate
+    // call to objc_msgSend_stret and hang both varieties on a conditional
+    // expression which dictate which one to envoke depending on size of
+    // method's return type.
+    
+    // Create a reference to the objc_msgSend_stret() declaration.
+    DeclRefExpr *STDRE = new DeclRefExpr(MsgSendStretFlavor, msgSendType, 
+                                         SourceLocation());
+    // Need to cast objc_msgSend_stret to "void *" (see above comment).
+    cast = new CastExpr(Context->getPointerType(Context->VoidTy), STDRE, 
+                        SourceLocation());
+    // Now do the "normal" pointer to function cast.
+    castType = Context->getFunctionType(returnType, 
+                                        &ArgTypes[0], ArgTypes.size(),
+                                        Exp->getMethodDecl()->isVariadic());
+    castType = Context->getPointerType(castType);
+    cast = new CastExpr(castType, cast, SourceLocation());
+    
+    // Don't forget the parens to enforce the proper binding.
+    PE = new ParenExpr(SourceLocation(), SourceLocation(), cast);
+    
+    FT = msgSendType->getAsFunctionType();
+    CallExpr *STCE = new CallExpr(PE, &MsgExprs[0], MsgExprs.size(), 
+                                  FT->getResultType(), SourceLocation());
+    
+    // Build sizeof(returnType)
+    SizeOfAlignOfTypeExpr *sizeofExpr = new SizeOfAlignOfTypeExpr(true, 
+                                          returnType, Context->getSizeType(), 
+                                          SourceLocation(), SourceLocation());
+    // (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...))
+    // FIXME: Value of 8 is base on ppc32/x86 ABI for the most common cases.
+    // For X86 it is more complicated and some kind of target specific routine
+    // is needed to decide what to do.
+    unsigned IntSize = static_cast<unsigned>(
+      Context->getTypeSize(Context->IntTy, SourceLocation()));
+
+    IntegerLiteral *limit = new IntegerLiteral(llvm::APInt(IntSize, 8), 
+                                               Context->IntTy,
+                                               SourceLocation());
+    BinaryOperator *lessThanExpr = new BinaryOperator(sizeofExpr, limit, 
+                                                      BinaryOperator::LE, 
+                                                      Context->IntTy, 
+                                                      SourceLocation());
+    // (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...))
+    ConditionalOperator *CondExpr = 
+      new ConditionalOperator(lessThanExpr, CE, STCE, returnType);
+    ParenExpr *PE = new ParenExpr(SourceLocation(), SourceLocation(), CondExpr);
+    // Now do the actual rewrite.
+    Rewrite.ReplaceStmt(Exp, PE);
+    delete Exp;
+    return PE;
+  }
   // Now do the actual rewrite.
   Rewrite.ReplaceStmt(Exp, CE);
   
@@ -1327,11 +1445,6 @@
   if (ObjcSynthesizedStructs.count(CDecl))
     return;
   ObjcInterfaceDecl *RCDecl = CDecl->getSuperClass();
-  if (RCDecl && !ObjcSynthesizedStructs.count(RCDecl)) {
-    // Do it for the root
-    SynthesizeObjcInternalStruct(RCDecl, Result);
-  }
-  
   int NumIvars = CDecl->getNumInstanceVariables();
   SourceLocation LocStart = CDecl->getLocStart();
   SourceLocation LocEnd = CDecl->getLocEnd();





More information about the cfe-commits mailing list