Add NeXT runtime support for generating methods.

Change CodeGenFunction::EmitParmDecl to take either a ParmVarDecl or an
  ImplicitParamDecl.

Drop hasAggregateLLVMType from CodeGenModule.cpp (use version in
  CodeGenFunction).

Change the Objective-C method generation to use EmitParmDecl for
  implicit parameters.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@54838 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp
index 61b9534..8cb1536 100644
--- a/lib/CodeGen/CGObjCMac.cpp
+++ b/lib/CodeGen/CGObjCMac.cpp
@@ -14,6 +14,7 @@
 #include "CGObjCRuntime.h"
 
 #include "CodeGenModule.h"
+#include "CodeGenFunction.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclObjC.h"
@@ -22,6 +23,7 @@
 #include "llvm/Module.h"
 #include "llvm/Support/IRBuilder.h"
 #include "llvm/Target/TargetData.h"
+#include <sstream>
 
 using namespace clang;
 
@@ -194,6 +196,11 @@
   /// the name.
   llvm::Constant *GetMethodVarType(ObjCMethodDecl *D);
 
+  /// GetNameForMethod - Return a name for the given method.
+  /// \param[out] NameOut - The return value.
+  void GetNameForMethod(const ObjCMethodDecl *OMD,
+                        std::string &NameOut);
+
 public:
   CGObjCMac(CodeGen::CodeGenModule &cgm);
   virtual llvm::Constant *GenerateConstantString(const std::string &String);
@@ -606,7 +613,57 @@
 }
 
 void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ClassDecl) {
-  assert(0 && "Cannot generate class for Mac runtime.");
+  //assert(0 && "Cannot generate class for Mac runtime.");
+}
+
+llvm::Function *CGObjCMac::GenerateMethod(const ObjCMethodDecl *OMD) { 
+  const llvm::Type *ReturnTy = 
+    CGM.getTypes().ConvertReturnType(OMD->getResultType());
+  const llvm::Type *SelfTy = 
+    CGM.getTypes().ConvertType(OMD->getSelfDecl()->getType());
+
+  std::vector<const llvm::Type*> ArgTys;
+  ArgTys.reserve(1 + 2 + OMD->param_size());
+
+  // FIXME: This is not something we should have to be dealing with
+  // here.
+  bool useStructRet = 
+    CodeGen::CodeGenFunction::hasAggregateLLVMType(OMD->getResultType());
+  if (useStructRet) {
+    ArgTys.push_back(llvm::PointerType::getUnqual(ReturnTy));
+    ReturnTy = llvm::Type::VoidTy;
+  }
+
+  // Implicit arguments
+  ArgTys.push_back(SelfTy);
+  ArgTys.push_back(ObjCTypes.SelectorPtrTy);
+
+  for (ObjCMethodDecl::param_const_iterator 
+         i = OMD->param_begin(), e = OMD->param_end();
+       i != e; ++i) {
+    const llvm::Type *Ty = CGM.getTypes().ConvertType((*i)->getType());
+    if (Ty->isFirstClassType()) {
+      ArgTys.push_back(Ty);
+    } else {
+      ArgTys.push_back(llvm::PointerType::getUnqual(Ty));
+    }
+  }
+
+  std::string Name;
+  GetNameForMethod(OMD, Name);
+
+  llvm::Function *Method = 
+    llvm::Function::Create(llvm::FunctionType::get(ReturnTy,
+                                                   ArgTys,
+                                                   OMD->isVariadic()),
+                           llvm::GlobalValue::InternalLinkage,
+                           Name,
+                           &CGM.getModule());
+
+  if (useStructRet)
+    Method->addParamAttr(1, llvm::ParamAttr::StructRet);
+
+  return Method;
 }
 
 llvm::Function *CGObjCMac::ModuleInitFunction() { 
@@ -616,11 +673,6 @@
   return NULL;
 }
 
-llvm::Function *CGObjCMac::GenerateMethod(const ObjCMethodDecl *OMD) {
-  assert(0 && "Cannot generate method preamble for Mac runtime.");
-  return 0;
-}
-
 /* *** Private Interface *** */
 
 /// EmitImageInfo - Emit the image info marker used to encode some module
@@ -786,6 +838,19 @@
   return getConstantGEP(Entry, 0, 0);
 }
 
+void CGObjCMac::GetNameForMethod(const ObjCMethodDecl *D, 
+                                 std::string &NameOut) {
+  // FIXME: Find the mangling GCC uses.
+  std::stringstream s;
+  s << (D->isInstance() ? "-" : "+");
+  s << "[";
+  s << D->getClassInterface()->getName();
+  s << " ";
+  s << D->getSelector().getName();
+  s << "]";
+  NameOut = s.str();
+}
+
 void CGObjCMac::FinishModule() {
   EmitModuleInfo();