Index: CGObjCRuntime.h
===================================================================
--- CGObjCRuntime.h	(revision 0)
+++ CGObjCRuntime.h	(revision 0)
@@ -0,0 +1,46 @@
+//===----- CGObjCRuntime.h - Emit LLVM Code from ASTs for a Module --------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This provides an abstract class for Objective-C code generation.  Concrete
+// subclasses of this implement code generation for specific Objective-C
+// runtime libraries.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef __CODEGENOBJC_H_INCLUDED__
+#define __CODEGENOBJC_H_INCLUDED__
+#include "clang/AST/AST.h"
+#include "clang/AST/Expr.h"
+
+#include "llvm/Constants.h"
+#include "llvm/Function.h"
+#include "llvm/GlobalVariable.h"
+#include "llvm/Intrinsics.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/LLVMBuilder.h"
+#include "llvm/Module.h"
+
+using llvm::Value;
+
+namespace clang {
+namespace CodeGen {
+  class CodeGenModule;
+// Implements runtime-specific code generation functions
+  class CGObjCRuntime {
+    public:
+      virtual Value *generateMessageSend(llvm::LLVMFoldingBuilder &Builder,
+                                         llvm::Value *Receiver,
+                                         llvm::Constant *Selector,
+                                         llvm::Value** ArgV,
+                                         size_t ArgC) = 0;
+  };
+  CGObjCRuntime * ObjCDefaultRuntime(llvm::Module &M);
+}
+}
+#endif
Index: CGObjCGNU.cpp
===================================================================
--- CGObjCGNU.cpp	(revision 0)
+++ CGObjCGNU.cpp	(revision 0)
@@ -0,0 +1,115 @@
+//===------- CGObjCGNU.cpp - Emit LLVM Code from ASTs for a Module --------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This provides Objective-C code generation targetting the GNU runtime.
+//
+//===----------------------------------------------------------------------===//
+#include "CGObjCRuntime.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/Type.h"
+#include <vector>
+
+using namespace clang::CodeGen;
+using namespace clang;
+using namespace llvm;
+
+class CGObjCGNU : public CGObjCRuntime {
+private:
+  Module &TheModule;
+public:
+  CGObjCGNU(Module &M) : TheModule(M) {};
+  virtual Value *generateMessageSend(llvm::LLVMFoldingBuilder &Builder,
+                                     llvm::Value *Receiver,
+                                     llvm::Constant *Selector,
+                                     llvm::Value** ArgV,
+                                     size_t ArgC);
+};
+
+// Generate code for a message send expression on the GNU runtime.
+// BIG FAT WARNING: Much of this code will need factoring out later.
+// FIXME: This currently only handles id returns.  Other return types 
+// need some explicit casting.
+Value *CGObjCGNU::generateMessageSend(llvm::LLVMFoldingBuilder &Builder,
+                                           llvm::Value * Receiver,
+                                           llvm::Constant *Selector,
+                                           llvm::Value** ArgV,
+                                           size_t ArgC) {
+  // Selector Type
+  std::vector<const llvm::Type*> Str2(2,
+      llvm::PointerType::get(llvm::Type::Int8Ty, 0));
+  const llvm::Type *STy = llvm::StructType::get(Str2);
+  const llvm::Type *SelType = llvm::PointerType::get(STy, 0);
+
+  // Look up the selector
+  Function *SelFunction = TheModule.getFunction("sel_get_uid");
+  // If we haven't got the selector lookup function, look it up now.
+  // TODO: Factor this out and use it to implement @selector() too.
+  if(SelFunction == 0) {
+    std::vector<const llvm::Type*> Str(1,
+        llvm::PointerType::get(llvm::Type::Int8Ty, 0));
+    const llvm::FunctionType *SelLookupType = llvm::FunctionType::get(SelType,
+        Str,
+        false);
+    const std::string SelLookup("sel_get_uid");
+    SelFunction = new Function((const llvm::FunctionType*)SelLookupType, 
+        Function::ExternalLinkage, 
+        SelLookup, 
+        &TheModule);
+  }
+  
+  // FIXME: Selectors should be statically cached, not looked up on every call.
+  std::vector<Value*> SelArgs;
+  std::vector<Value*> IdxVector;
+  // TODO: Pull this out into the caller.
+  llvm::Constant *Idx0 = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0);
+  llvm::Constant *Ops[] = {Idx0, Idx0};
+  llvm::Value *SelStr = llvm::ConstantExpr::getGetElementPtr(Selector, Ops, 2);
+  SelArgs.push_back(SelStr);
+  Value *cmd = Builder.CreateCall(SelFunction, SelArgs.begin(), SelArgs.end());
+
+  // Look up the method implementation
+  std::vector<const llvm::Type*> impArgTypes;
+  impArgTypes.push_back(Receiver->getType());
+  impArgTypes.push_back(SelType);
+  // FIXME: Return value should be passed in as an argument.  Type should be
+  // taken from that.
+  llvm::FunctionType *impType = llvm::FunctionType::get(Receiver->getType(), 
+      impArgTypes, 
+      true);
+  Function *lookupFunction = TheModule.getFunction("objc_msg_lookup");
+  if(lookupFunction == 0) {
+    std::vector<const llvm::Type*> lookupArgTypes;
+    lookupArgTypes.push_back(Receiver->getType());
+    lookupArgTypes.push_back(SelType);
+    llvm::FunctionType *LookupType = llvm::FunctionType::get(
+        llvm::PointerType::get(impType, 0), 
+        lookupArgTypes, false);
+    const std::string lookup("objc_msg_lookup");
+    lookupFunction = new Function(LookupType, 
+        Function::ExternalLinkage, 
+        lookup, 
+        &TheModule);
+  }
+  std::vector<Value*> lookupArgs;
+  lookupArgs.push_back(Receiver);
+  lookupArgs.push_back(cmd);
+  llvm::Value *imp = Builder.CreateCall(lookupFunction,
+      lookupArgs.begin(), 
+      lookupArgs.end());
+
+  // Call the method
+  for(size_t i=0 ; i<ArgC ; i++) {
+    lookupArgs.push_back(ArgV[i]);
+  }
+  return Builder.CreateCall(imp, lookupArgs.begin(), lookupArgs.end());
+}
+CGObjCRuntime * clang::CodeGen::ObjCDefaultRuntime(Module &M)
+{
+  return new CGObjCGNU(M);
+}
Index: CGExprConstant.cpp
===================================================================
--- CGExprConstant.cpp	(revision 47715)
+++ CGExprConstant.cpp	(working copy)
@@ -200,6 +200,9 @@
     
     // Make sure we have an array at this point
     assert(0 && "Unable to handle InitListExpr");
+    // Get rid of control reaches end of void function warning.
+    // Not reached.
+    return 0;
   }
 
   llvm::Constant *VisitImplicitCastExpr(ImplicitCastExpr *ICExpr) {
Index: CodeGenModule.cpp
===================================================================
--- CodeGenModule.cpp	(revision 47715)
+++ CodeGenModule.cpp	(working copy)
@@ -31,7 +31,10 @@
                              llvm::Module &M, const llvm::TargetData &TD,
                              Diagnostic &diags)
   : Context(C), Features(LO), TheModule(M), TheTargetData(TD), Diags(diags),
-    Types(C, M, TD), MemCpyFn(0), MemSetFn(0), CFConstantStringClassRef(0) {}
+    Types(C, M, TD), MemCpyFn(0), MemSetFn(0), CFConstantStringClassRef(0) {
+  //TODO: Make this selectable at runtime
+  Runtime = ObjCDefaultRuntime(M);
+}
 
 /// WarnUnsupported - Print out a warning that codegen doesn't support the
 /// specified stmt yet.
Index: CGExprScalar.cpp
===================================================================
--- CGExprScalar.cpp	(revision 47715)
+++ CGExprScalar.cpp	(working copy)
@@ -41,9 +41,14 @@
   : public StmtVisitor<ScalarExprEmitter, Value*> {
   CodeGenFunction &CGF;
   llvm::LLVMFoldingBuilder &Builder;
+  CGObjCRuntime *Runtime;
+
+
 public:
 
-  ScalarExprEmitter(CodeGenFunction &cgf) : CGF(cgf), Builder(CGF.Builder) {
+  ScalarExprEmitter(CodeGenFunction &cgf) : CGF(cgf), 
+    Builder(CGF.Builder), 
+    Runtime(CGF.CGM.getObjCRuntime()) {
   }
 
   
@@ -120,6 +125,7 @@
       return llvm::ConstantInt::get(EC->getInitVal());
     return EmitLoadOfLValue(E);
   }
+  Value *VisitObjCMessageExpr(ObjCMessageExpr *E);
   Value *VisitArraySubscriptExpr(ArraySubscriptExpr *E);
   Value *VisitMemberExpr(Expr *E)           { return EmitLoadOfLValue(E); }
   Value *VisitOCUVectorElementExpr(Expr *E) { return EmitLoadOfLValue(E); }
@@ -443,6 +449,46 @@
   return llvm::UndefValue::get(CGF.ConvertType(E->getType()));
 }
 
+Value *ScalarExprEmitter::VisitObjCMessageExpr(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.
+  
+  // Find the receiver
+  llvm::Value * Receiver = CGF.EmitScalarExpr(E->getReceiver());
+
+  // Process the arguments
+  unsigned int ArgC = E->getNumArgs();
+  llvm::SmallVector<llvm::Value*, 16> Args;
+  for(unsigned i=0 ; i<ArgC ; i++) {
+    Expr *ArgExpr = E->getArg(i);
+    QualType ArgTy = ArgExpr->getType();
+    if (!CGF.hasAggregateLLVMType(ArgTy)) {
+      // Scalar argument is passed by-value.
+      Args.push_back(CGF.EmitScalarExpr(ArgExpr));
+    } else if (ArgTy->isComplexType()) {
+      // Make a temporary alloca to pass the argument.
+      llvm::Value *DestMem = CGF.CreateTempAlloca(ConvertType(ArgTy));
+      CGF.EmitComplexExprIntoAddr(ArgExpr, DestMem, false);
+      Args.push_back(DestMem);
+    } else {
+      llvm::Value *DestMem = CGF.CreateTempAlloca(ConvertType(ArgTy));
+      CGF.EmitAggExpr(ArgExpr, DestMem, false);
+      Args.push_back(DestMem);
+    }
+  }
+
+  // Get the selector string
+  std::string SelStr = E->getSelector().getName();
+  llvm::Constant *Selector = CGF.CGM.GetAddrOfConstantString(SelStr);
+
+  return Runtime->generateMessageSend(Builder,
+      Receiver,
+      Selector,
+      &Args[0],
+      Args.size());
+}
+
 Value *ScalarExprEmitter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
   // Emit subscript expressions in rvalue context's.  For most cases, this just
   // loads the lvalue formed by the subscript expr.  However, we have to be
Index: CodeGenModule.h
===================================================================
--- CodeGenModule.h	(revision 47715)
+++ CodeGenModule.h	(working copy)
@@ -15,6 +15,7 @@
 #define CODEGEN_CODEGENMODULE_H
 
 #include "CodeGenTypes.h"
+#include "CGObjCRuntime.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/StringMap.h"
 
@@ -52,6 +53,7 @@
   const llvm::TargetData &TheTargetData;
   Diagnostic &Diags;
   CodeGenTypes Types;
+  CGObjCRuntime *Runtime;
 
   llvm::Function *MemCpyFn;
   llvm::Function *MemSetFn;
@@ -66,6 +68,7 @@
   CodeGenModule(ASTContext &C, const LangOptions &Features, llvm::Module &M, 
                 const llvm::TargetData &TD, Diagnostic &Diags);
   
+  CGObjCRuntime *getObjCRuntime() { return Runtime; }
   ASTContext &getContext() const { return Context; }
   const LangOptions &getLangOptions() const { return Features; }
   llvm::Module &getModule() const { return TheModule; }
