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: CodeGenObjC.h
===================================================================
--- CodeGenObjC.h	(revision 0)
+++ CodeGenObjC.h	(revision 0)
@@ -0,0 +1,30 @@
+#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"
+
+using llvm::Value;
+
+namespace clang {
+namespace CodeGen {
+  class CodeGenModule;
+// Implements runtime-specific code generation functions
+  class CodeGenObjCRuntime {
+    public:
+      virtual Value *generateMessageSend(llvm::LLVMFoldingBuilder &B,
+                                         llvm::Value *receiver,
+                                         std::string &selector,
+                                         llvm::Value** ArgV,
+                                         size_t ArgC) = 0;
+  };
+  CodeGenObjCRuntime * ObjCDefaultRuntime(CodeGenModule * CGM);
+}
+}
+#endif
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
+  ObjC = ObjCDefaultRuntime(this);
+}
 
 /// WarnUnsupported - Print out a warning that codegen doesn't support the
 /// specified stmt yet.
Index: CodeGenObjCGNU.cpp
===================================================================
--- CodeGenObjCGNU.cpp	(revision 0)
+++ CodeGenObjCGNU.cpp	(revision 0)
@@ -0,0 +1,87 @@
+#include "CodeGenObjC.h"
+#include "CodeGenModule.h"
+#include "llvm/Module.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/Type.h"
+#include <vector>
+#include <iostream>
+
+using namespace clang::CodeGen;
+using namespace clang;
+using namespace llvm;
+
+class CodeGenObjCGNU : public CodeGenObjCRuntime {
+private:
+  CodeGenModule * CGM;
+public:
+  CodeGenObjCGNU(CodeGenModule * cgm) : CGM(cgm) {};
+  virtual Value *generateMessageSend(llvm::LLVMFoldingBuilder &B,
+                                     llvm::Value * receiver,
+                                     std::string &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 *CodeGenObjCGNU::generateMessageSend(llvm::LLVMFoldingBuilder &B,
+                                           llvm::Value * receiver,
+                                           std::string &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 *selType = llvm::PointerType::get((llvm::Type*)llvm::StructType::get(str2), 0);
+  Module &mod = CGM->getModule();
+  // Look up the selector
+  Function *selFunction = mod.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 *FT = llvm::FunctionType::get(selType, str, false);
+    const std::string selLookup("sel_get_uid");
+    selFunction = new Function((const llvm::FunctionType*)FT, Function::ExternalLinkage, selLookup, &mod);
+  }
+  // FIXME: Selectors should be statically cached, not looked up on every call.
+  std::vector<Value*> selArgs;
+  std::vector<Value*> index_vector;
+  // TODO: Pull this out into the caller.
+  llvm::Constant *sel_str = CGM->GetAddrOfConstantString(selector);
+  llvm::Constant *Idx0 = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0);
+  llvm::Constant *Ops[] = {Idx0, Idx0};
+  sel_str = llvm::ConstantExpr::getGetElementPtr(sel_str, Ops, 2);
+  selArgs.push_back(sel_str);
+  Value *cmd = B.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 = mod.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((const llvm::FunctionType*)lookupType, Function::ExternalLinkage, lookup, &mod);
+  }
+  std::vector<Value*> lookupArgs;
+  lookupArgs.push_back(receiver);
+  lookupArgs.push_back(cmd);
+  llvm::Value *imp = B.CreateCall(lookupFunction, lookupArgs.begin(), lookupArgs.end());
+  for(size_t i=0 ; i<ArgC ; i++) {
+    lookupArgs.push_back(ArgV[i]);
+  }
+  B.CreateCall(imp, lookupArgs.begin(), lookupArgs.end());
+  return 0;
+}
+CodeGenObjCRuntime * clang::CodeGen::ObjCDefaultRuntime(CodeGenModule * CGM)
+{
+  return new CodeGenObjCGNU(CGM);
+}
Index: CGExprScalar.cpp
===================================================================
--- CGExprScalar.cpp	(revision 47715)
+++ CGExprScalar.cpp	(working copy)
@@ -120,6 +120,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 +444,34 @@
   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.
+  llvm::Value * receiver = CGF.EmitScalarExpr(E->getReceiver());
+  std::string selector = E->getSelector().getName();
+  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);
+    }
+  }
+  return CGF.CGM.getObjCRuntime()->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 "CodeGenObjC.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/StringMap.h"
 
@@ -52,6 +53,7 @@
   const llvm::TargetData &TheTargetData;
   Diagnostic &Diags;
   CodeGenTypes Types;
+  CodeGenObjCRuntime *ObjC;
 
   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);
   
+  CodeGenObjCRuntime *getObjCRuntime() { return ObjC; }
   ASTContext &getContext() const { return Context; }
   const LangOptions &getLangOptions() const { return Features; }
   llvm::Module &getModule() const { return TheModule; }
Index: ModuleBuilder.cpp
===================================================================
--- ModuleBuilder.cpp	(revision 47715)
+++ ModuleBuilder.cpp	(working copy)
@@ -27,6 +27,7 @@
 #include "llvm/Module.h"
 #include "llvm/Target/TargetData.h"
 #include "llvm/Target/TargetMachine.h"
+#include "CodeGenObjC.h"
 
 namespace {
   class CodeGenerator : public ASTConsumer {
@@ -63,6 +64,20 @@
       
       if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
         Builder->EmitFunction(FD);
+      } else if (dyn_cast<ObjCClassDecl>(D)){
+        //Forward declaration.  Only used for type checking.
+      } else if (dyn_cast<ObjCProtocolDecl>(D)){
+        // TODO: Generate Protocol object.
+      } else if (dyn_cast<ObjCCategoryDecl>(D)){
+        //Only used for typechecking.
+      } else if (dyn_cast<ObjCCategoryImplDecl>(D)){
+        // TODO: Generate methods, attach to class structure
+      } else if (dyn_cast<ObjCImplementationDecl>(D)){
+        // TODO: Generate methods, attach to class structure
+      } else if (dyn_cast<ObjCInterfaceDecl>(D)){
+        // TODO: Set up class structure
+      } else if (dyn_cast<ObjCMethodDecl>(D)){
+        // TODO: Emit method, add method pointer to class structure.
       } else if (FileVarDecl *FVD = dyn_cast<FileVarDecl>(D)) {
         Builder->EmitGlobalVarDeclarator(FVD);
       } else if (LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(D)) {
