[cfe-commits] r52681 - in /cfe/trunk/lib/CodeGen: CGExprAgg.cpp CGObjC.cpp CGObjCGNU.cpp CodeGenFunction.h

Chris Lattner sabre at nondot.org
Tue Jun 24 10:04:18 PDT 2008


Author: lattner
Date: Tue Jun 24 12:04:18 2008
New Revision: 52681

URL: http://llvm.org/viewvc/llvm-project?rev=52681&view=rev
Log:
"Support for Objective-C message sends which return structures.  Also includes a small fix for constant string handling that should have been in the last patch (sorry!) and a hook for generating selectors (rest of this implementation to follow in the next patch)."

Patch by David Chisnall!


Modified:
    cfe/trunk/lib/CodeGen/CGExprAgg.cpp
    cfe/trunk/lib/CodeGen/CGObjC.cpp
    cfe/trunk/lib/CodeGen/CGObjCGNU.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.h

Modified: cfe/trunk/lib/CodeGen/CGExprAgg.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprAgg.cpp?rev=52681&r1=52680&r2=52681&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprAgg.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprAgg.cpp Tue Jun 24 12:04:18 2008
@@ -86,6 +86,8 @@
   void VisitOverloadExpr(const OverloadExpr *E);
   void VisitBinComma(const BinaryOperator *E);
 
+  void VisitObjCMessageExpr(ObjCMessageExpr *E);
+
   
   void VisitConditionalOperator(const ConditionalOperator *CO);
   void VisitInitListExpr(InitListExpr *E);
@@ -202,6 +204,16 @@
   
   EmitAggregateCopy(DestPtr, RV.getAggregateAddr(), E->getType());
 }
+void AggExprEmitter::VisitObjCMessageExpr(ObjCMessageExpr *E) 
+{
+  RValue RV = RValue::getAggregate(CGF.EmitObjCMessageExpr(E));
+
+  // If the result is ignored, don't copy from the value.
+  if (DestPtr == 0)
+    return;
+  
+  EmitAggregateCopy(DestPtr, RV.getAggregateAddr(), E->getType());
+}
 
 void AggExprEmitter::VisitOverloadExpr(const OverloadExpr *E)
 {

Modified: cfe/trunk/lib/CodeGen/CGObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjC.cpp?rev=52681&r1=52680&r2=52681&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjC.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjC.cpp Tue Jun 24 12:04:18 2008
@@ -21,9 +21,88 @@
 using namespace clang;
 using namespace CodeGen;
 
+/// Emits an instance of NSConstantString representing the object.
 llvm::Value *CodeGenFunction::EmitObjCStringLiteral(const ObjCStringLiteral *E){
-  std::string S(E->getString()->getStrData(), E->getString()->getByteLength());
-  return CGM.GetAddrOfConstantCFString(S);
+  return CGM.getObjCRuntime()->GenerateConstantString(
+      E->getString()->getStrData(), E->getString()->getByteLength());
+}
+
+/// Emit a selector.
+llvm::Value *CodeGenFunction::EmitObjCSelectorExpr(const ObjCSelectorExpr *E) {
+  // Untyped selector.
+  // Note that this implementation allows for non-constant strings to be passed
+  // as arguments to @selector().  Currently, the only thing preventing this
+  // behaviour is the type checking in the front end.
+  return CGM.getObjCRuntime()->GetSelector(Builder,
+      CGM.GetAddrOfConstantString(E->getSelector().getName()), 0);
+}
+
+
+
+llvm::Value *CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E) {
+  // Only the lookup mechanism and first two arguments of the method
+  // implementation vary between runtimes.  We can get the receiver and
+  // arguments in generic code.
+  
+  CGObjCRuntime *Runtime = CGM.getObjCRuntime();
+  const Expr *ReceiverExpr = E->getReceiver();
+  bool isSuperMessage = false;
+  // Find the receiver
+  llvm::Value *Receiver;
+  if (!ReceiverExpr) {
+    const char * classname = E->getClassName()->getName();
+    if (!strcmp(classname, "super")) {
+      classname = E->getMethodDecl()->getClassInterface()->getName();
+    }
+    llvm::Value *ClassName = CGM.GetAddrOfConstantString(classname);
+    ClassName = Builder.CreateStructGEP(ClassName, 0);
+    Receiver = Runtime->LookupClass(Builder, ClassName);
+  } else if (dyn_cast<PreDefinedExpr>(E->getReceiver())) {
+    isSuperMessage = true;
+    Receiver = LoadObjCSelf();
+  } else {
+   Receiver = EmitScalarExpr(E->getReceiver());
+  }
+
+  // Process the arguments
+  unsigned ArgC = E->getNumArgs();
+  llvm::SmallVector<llvm::Value*, 16> Args;
+  for (unsigned i = 0; i != ArgC; ++i) {
+    const Expr *ArgExpr = E->getArg(i);
+    QualType ArgTy = ArgExpr->getType();
+    if (!hasAggregateLLVMType(ArgTy)) {
+      // Scalar argument is passed by-value.
+      Args.push_back(EmitScalarExpr(ArgExpr));
+    } else if (ArgTy->isAnyComplexType()) {
+      // Make a temporary alloca to pass the argument.
+      llvm::Value *DestMem = CreateTempAlloca(ConvertType(ArgTy));
+      EmitComplexExprIntoAddr(ArgExpr, DestMem, false);
+      Args.push_back(DestMem);
+    } else {
+      llvm::Value *DestMem = CreateTempAlloca(ConvertType(ArgTy));
+      EmitAggExpr(ArgExpr, DestMem, false);
+      Args.push_back(DestMem);
+    }
+  }
+
+  // Get the selector string
+  std::string SelStr = E->getSelector().getName();
+  llvm::Constant *Selector = CGM.GetAddrOfConstantString(SelStr);
+
+  llvm::Value *SelPtr = Builder.CreateStructGEP(Selector, 0);
+  if (isSuperMessage) {
+    const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(CurFuncDecl);
+    assert(OMD && "super is only valid in an Objective-C method");
+    const char *SuperClass = OMD->getClassInterface()->getSuperClass()->getName();
+    return Runtime->GenerateMessageSendSuper(Builder, ConvertType(E->getType()),
+                                        Receiver, SuperClass,
+                                        Receiver, SelPtr,
+                                        &Args[0], Args.size());
+  }
+  return Runtime->GenerateMessageSend(Builder, ConvertType(E->getType()),
+                                      LoadObjCSelf(),
+                                      Receiver, SelPtr,
+                                      &Args[0], Args.size());
 }
 
 /// Generate an Objective-C method.  An Objective-C method is a C function with

Modified: cfe/trunk/lib/CodeGen/CGObjCGNU.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCGNU.cpp?rev=52681&r1=52680&r2=52681&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCGNU.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCGNU.cpp Tue Jun 24 12:04:18 2008
@@ -405,11 +405,14 @@
   if (!ReturnTy->isSingleValueType()) {
     llvm::Value *Return = Builder.CreateAlloca(ReturnTy);
     Args.push_back(Return);
-    return Return;
   }
   Args.push_back(Receiver);
   Args.push_back(cmd);
   Args.insert(Args.end(), ArgV, ArgV+ArgC);
+  if (!ReturnTy->isSingleValueType()) {
+    Builder.CreateCall(imp, Args.begin(), Args.end());
+    return Args[0];
+  }
   return Builder.CreateCall(imp, Args.begin(), Args.end());
 }
 
@@ -887,7 +890,7 @@
                                          bool isClassMethod,
                                          bool isVarArg) {
   std::vector<const llvm::Type*> Args;
-  if (!ReturnTy->isFirstClassType() && ReturnTy != llvm::Type::VoidTy) {
+  if (!ReturnTy->isSingleValueType() && ReturnTy != llvm::Type::VoidTy) {
     Args.push_back(llvm::PointerType::getUnqual(ReturnTy));
     ReturnTy = llvm::Type::VoidTy;
   }

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=52681&r1=52680&r2=52681&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Tue Jun 24 12:04:18 2008
@@ -451,6 +451,10 @@
                           bool isSplat = false);
   
   llvm::Value *EmitObjCStringLiteral(const ObjCStringLiteral *E);
+  llvm::Value *EmitObjCSelectorExpr(const ObjCSelectorExpr *E);
+  llvm::Value *EmitObjCMessageExpr(const ObjCMessageExpr *E);
+
+
 
   //===--------------------------------------------------------------------===//
   //                           Expression Emission





More information about the cfe-commits mailing list