Index: CodeGenTypes.h
===================================================================
--- CodeGenTypes.h	(revision 48734)
+++ CodeGenTypes.h	(working copy)
@@ -34,6 +34,8 @@
   class FunctionTypeProto;
   class FieldDecl;
   class RecordDecl;
+  class ObjCInterfaceDecl;
+  class ObjCIvarDecl;
 
 namespace CodeGen {
   class CodeGenTypes;
@@ -128,12 +130,15 @@
   /// memory representation is usually i8 or i32, depending on the target.
   const llvm::Type *ConvertTypeForMem(QualType T);
   
+  void CollectObjCIvarTypes(ObjCInterfaceDecl *ObjCClass,
+      std::vector<const llvm::Type*> &IvarTypes);
   
   const CGRecordLayout *getCGRecordLayout(const TagDecl*) const;
   
   /// getLLVMFieldNo - Return llvm::StructType element number
   /// that corresponds to the field FD.
   unsigned getLLVMFieldNo(const FieldDecl *FD);
+  unsigned getLLVMFieldNo(QualType ObjectTy, const ObjCIvarDecl *Decl);
     
   
   /// UpdateCompletedType - When we find the full definition for a TagDecl,
Index: CGObjCRuntime.h
===================================================================
--- CGObjCRuntime.h	(revision 48734)
+++ CGObjCRuntime.h	(working copy)
@@ -22,8 +22,10 @@
   class Type;
   class Value;
   class Module;
+  class Function;
 }
 
+
 namespace clang {
 namespace CodeGen {
 
@@ -32,16 +34,35 @@
 public:
   virtual ~CGObjCRuntime();
   
-  // Generate an Objective-C message send operation
+  /// Generate an Objective-C message send operation
   virtual llvm::Value *generateMessageSend(llvm::LLVMFoldingBuilder &Builder,
                                            const llvm::Type *ReturnTy,
+                                           llvm::Value *Sender,
                                            llvm::Value *Receiver,
-                                           llvm::Constant *Selector,
+                                           llvm::Value *Selector,
                                            llvm::Value** ArgV,
                                            unsigned ArgC) = 0;
+  /// Generate the function required to register all Objective-C components in
+  /// this compilation unit with the runtime library.
+  virtual llvm::Function *ModuleInitFunction() { return 0; }
+  /// Generate a function preamble for a method with the specified types
+  virtual llvm::Function *MethodPreamble(const llvm::Type *ReturnTy,
+                                         const llvm::Type *SelfTy,
+                                         const llvm::Type **ArgTy,
+                                         unsigned ArgC,
+                                         bool isVarArg) = 0;
+  /// If instance variable addresses are determined at runtime then this should
+  /// return true, otherwise instance variables will be accessed directly from
+  /// the structure.  If this returns true then @defs is invalid for this
+  /// runtime and a warning should be generated.
+  virtual bool LateBoundIVars() { return false; }
 };
 
-CGObjCRuntime *CreateObjCRuntime(llvm::Module &M);
+/// Creates an instance of an Objective-C runtime class.  
+//TODO: This should include some way of selecting which runtime to target.
+CGObjCRuntime *CreateObjCRuntime(llvm::Module &M,
+                                 const llvm::Type *LLVMIntType,
+                                 const llvm::Type *LLVMLongType);
 }
 }
 #endif
Index: CGObjCGNU.cpp
===================================================================
--- CGObjCGNU.cpp	(revision 48734)
+++ CGObjCGNU.cpp	(working copy)
@@ -1,4 +1,4 @@
-//===------- CGObjCGNU.cpp - Emit LLVM Code from ASTs for a Module --------===//
+//===------- CGObjCGNU.cpp - Emit LLVM Code from ASTs for a Module --------===// 
 //
 //                     The LLVM Compiler Infrastructure
 //
@@ -11,66 +11,152 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include <stdarg.h>
 #include "CGObjCRuntime.h"
 #include "llvm/Module.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/LLVMBuilder.h"
 #include "llvm/ADT/SmallVector.h"
 
-using namespace clang::CodeGen;
-using namespace clang;
 
-CGObjCRuntime::~CGObjCRuntime() {}
+clang::CodeGen::CGObjCRuntime::~CGObjCRuntime() {}
 
 namespace {
-class CGObjCGNU : public CGObjCRuntime {
+class CGObjCGNU : public clang::CodeGen::CGObjCRuntime {
 private:
   llvm::Module &TheModule;
+  const llvm::Type *SelectorTy;
+  const llvm::Type *PtrToInt8Ty;
+  const llvm::Type *IMPTy;
+  const llvm::Type *IdTy;
+  const llvm::Type *IntTy;
+  const llvm::Type *PtrTy;
+  const llvm::Type *LongTy;
+  const llvm::Type *PtrToIntTy;
 public:
-  CGObjCGNU(llvm::Module &M) : TheModule(M) {};
+  CGObjCGNU(llvm::Module &Mp,
+    const llvm::Type *LLVMIntType,
+    const llvm::Type *LLVMLongType);
   virtual llvm::Value *generateMessageSend(llvm::LLVMFoldingBuilder &Builder,
                                            const llvm::Type *ReturnTy,
+                                           llvm::Value *Sender,
                                            llvm::Value *Receiver,
-                                           llvm::Constant *Selector,
+                                           llvm::Value *Selector,
                                            llvm::Value** ArgV,
                                            unsigned ArgC);
+  llvm::Value *getSelector(llvm::LLVMFoldingBuilder &Builder,
+      llvm::Value *SelName,
+      llvm::Value *SelTypes);
+  llvm::Value *GenerateIvarList(llvm::LLVMFoldingBuilder &Builder,
+      std::vector<llvm::Constant*> MethodNames,
+      std::vector<llvm::Constant*> MethodTypes,
+      std::vector<llvm::Constant*> MethodIMPs);
+  llvm::Value *GenerateMethodList(llvm::LLVMFoldingBuilder &Builder,
+      std::vector<llvm::Constant*> MethodNames,
+      std::vector<llvm::Constant*> MethodTypes,
+      std::vector<llvm::Constant*> MethodIMPs);
+  llvm::Value *GenerateClassStructure(
+      llvm::LLVMFoldingBuilder &Builder,
+      llvm::Value *MetaClass,
+      llvm::Value *SuperClass,
+      llvm::Value *Name,
+      llvm::Value *Version,
+      llvm::Value *InstanceSize,
+      llvm::Value *IVars,
+      llvm::Value *Methods);
+  virtual llvm::Function *MethodPreamble(const llvm::Type *ReturnTy,
+                                 const llvm::Type *SelfTy,
+                                 const llvm::Type **ArgTy,
+                                 unsigned ArgC,
+                                 bool isVarArg);
 };
 } // end anonymous namespace
 
-// 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.
+CGObjCGNU::CGObjCGNU(llvm::Module &M,
+    const llvm::Type *LLVMIntType,
+    const llvm::Type *LLVMLongType) : 
+  TheModule(M),
+  IntTy(LLVMIntType),
+  LongTy(LLVMLongType)
+{
+  // C string type.  Used in lots of places.
+  PtrToInt8Ty = 
+    llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
+  // Get the selector Type.
+  std::vector<const llvm::Type*> Str2(2, PtrToInt8Ty);
+  const llvm::Type *SelStructTy = llvm::StructType::get(Str2);
+  SelectorTy = llvm::PointerType::getUnqual(SelStructTy);
+  PtrToIntTy = llvm::PointerType::getUnqual(IntTy);
+  PtrTy = llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
+ 
+  // Object type
+  llvm::OpaqueType *OpaqueObjTy = llvm::OpaqueType::get();
+  llvm::Type *OpaqueIdTy = llvm::PointerType::getUnqual(OpaqueObjTy);
+  IdTy = llvm::PointerType::getUnqual(llvm::StructType::get(OpaqueIdTy, NULL));
+  OpaqueObjTy->refineAbstractTypeTo(IdTy);
+ 
+  // IMP type
+  std::vector<const llvm::Type*> IMPArgs;
+  IMPArgs.push_back(IdTy);
+  IMPArgs.push_back(SelectorTy);
+  IMPTy = llvm::FunctionType::get(IdTy, IMPArgs, true);
+
+}
+
+static void SetField(llvm::LLVMFoldingBuilder &Builder,
+                     llvm::Value *Structure, 
+                     unsigned Index, 
+                     llvm::Value *Value) {
+    llvm::Value *element_ptr = Builder.CreateStructGEP(Structure, Index);
+    Builder.CreateStore(Value, element_ptr);
+}
+
+/// Looks up the selector for the specified name / type pair.
+// FIXME: Selectors should be statically cached, not looked up on every call.
+llvm::Value *CGObjCGNU::getSelector(llvm::LLVMFoldingBuilder &Builder,
+    llvm::Value *SelName,
+    llvm::Value *SelTypes)
+{
+  // Look up the selector.
+  llvm::Value *cmd;
+  if(SelTypes == 0) {
+    llvm::Constant *SelFunction = 
+      TheModule.getOrInsertFunction("sel_get_uid", SelectorTy, PtrToInt8Ty, NULL);
+    cmd = Builder.CreateCall(SelFunction, SelName);
+  }
+  else {
+    llvm::Constant *SelFunction = 
+      TheModule.getOrInsertFunction("sel_get_typed_uid",
+          SelectorTy,
+          PtrToInt8Ty,
+          PtrToInt8Ty,
+          NULL);
+    llvm::SmallVector<llvm::Value*, 2> Args;
+    Args.push_back(SelName);
+    Args.push_back(SelTypes);
+    cmd = Builder.CreateCall(SelFunction, Args.begin(), Args.end());
+  }
+  return cmd;
+}
+
+
+/// Generate code for a message send expression on the GNU runtime.
+// FIXME: Much of this code will need factoring out later.
+// TODO: This should take a sender argument (pointer to self in the calling
+// context)
 llvm::Value *CGObjCGNU::generateMessageSend(llvm::LLVMFoldingBuilder &Builder,
                                             const llvm::Type *ReturnTy,
+                                            llvm::Value *Sender,
                                             llvm::Value *Receiver,
-                                            llvm::Constant *Selector,
+                                            llvm::Value *Selector,
                                             llvm::Value** ArgV,
                                             unsigned ArgC) {
-  // Get the selector Type.
-  const llvm::Type *PtrToInt8Ty = 
-    llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
-  const llvm::Type *SelStructTy = 
-    llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty, NULL);
-  const llvm::Type *SelTy = llvm::PointerType::getUnqual(SelStructTy);
+  llvm::Value *cmd = getSelector(Builder, Selector, 0);
 
-  // Look up the selector.
-  // If we haven't got the selector lookup function, look it up now.
-  // TODO: Factor this out and use it to implement @selector() too.
-  llvm::Constant *SelFunction = 
-    TheModule.getOrInsertFunction("sel_get_uid", SelTy, PtrToInt8Ty, NULL);
-  // FIXME: Selectors should be statically cached, not looked up on every call.
-
-  // 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);
-  llvm::Value *cmd = Builder.CreateCall(SelFunction, &SelStr, &SelStr+1);
-
   // Look up the method implementation.
   std::vector<const llvm::Type*> impArgTypes;
   impArgTypes.push_back(Receiver->getType());
-  impArgTypes.push_back(SelTy);
+  impArgTypes.push_back(SelectorTy);
   
   // Avoid an explicit cast on the IMP by getting a version that has the right
   // return type.
@@ -79,8 +165,8 @@
   
   llvm::Constant *lookupFunction = 
      TheModule.getOrInsertFunction("objc_msg_lookup",
-                                   llvm::PointerType::get(impType, 0),
-                                   Receiver->getType(), SelTy, NULL);
+                                   llvm::PointerType::getUnqual(impType),
+                                   Receiver->getType(), SelectorTy, NULL);
   llvm::SmallVector<llvm::Value*, 16> lookupArgs;
   lookupArgs.push_back(Receiver);
   lookupArgs.push_back(cmd);
@@ -92,6 +178,173 @@
   return Builder.CreateCall(imp, lookupArgs.begin(), lookupArgs.end());
 }
 
-CGObjCRuntime * clang::CodeGen::CreateObjCRuntime(llvm::Module &M) {
-  return new CGObjCGNU(M);
+/// Generates a MethodList.  Used in construction of a objc_class and 
+/// objc_category structures.
+llvm::Value *CGObjCGNU::GenerateMethodList(llvm::LLVMFoldingBuilder &Builder,
+    std::vector<llvm::Constant*> MethodNames,
+    std::vector<llvm::Constant*> MethodTypes,
+    std::vector<llvm::Constant*> MethodIMPs) {
+  // Get the method structure type.  
+  llvm::Type *ObjCMethodTy = llvm::StructType::get(
+    SelectorTy,
+    PtrToInt8Ty,
+    IMPTy,
+    NULL);
+
+  // Array of method structures
+  llvm::Type *ObjCMethodArrayTy = llvm::ArrayType::get(ObjCMethodTy,
+      MethodNames.size());
+
+  // Structure containing list pointer, array and array count
+  std::vector<const llvm::Type*> ObjCMethodListFields;
+  llvm::OpaqueType *OpaqueNextTy = llvm::OpaqueType::get();
+  llvm::Type *NextPtrTy = llvm::PointerType::getUnqual(OpaqueNextTy);
+
+  llvm::Type *ObjCMethodListTy = llvm::StructType::get(NextPtrTy, 
+      IntTy, 
+      ObjCMethodArrayTy,
+      NULL);
+
+  // Refine next pointer type to concrete type
+  OpaqueNextTy->refineAbstractTypeTo(
+      ObjCMethodListTy);
+
+  // Create an instance of the structure
+  llvm::Value *MethodList = Builder.CreateMalloc(ObjCMethodListTy);
+  llvm::Value *MethodArray = Builder.CreateStructGEP(MethodList, 3);
+  
+  // FIXME: This should use an iterator.  And possibly a more sensible
+  // data structure than just three vectors.
+  for(unsigned int i=0 ; i<1 ; i++) {
+    llvm::Value *MethodStruct = Builder.CreateStructGEP(MethodArray, i);
+    // Store the selector
+    llvm::Value *MethodNamePtr = Builder.CreateStructGEP(MethodStruct, NULL);
+    llvm::Value *Selector = getSelector(Builder, MethodNames[i], MethodTypes[i]);
+    Builder.CreateStore(Selector, MethodNamePtr);
+
+    // Store the types
+    llvm::Value *MethodTypesPtr = Builder.CreateStructGEP(MethodStruct, 1);
+    Builder.CreateStore(MethodTypes[i], MethodTypesPtr);
+
+    // Store the IMP
+    llvm::Value *MethodIMPPtr = Builder.CreateStructGEP(MethodStruct, 2);
+    Builder.CreateStore(MethodIMPs[i], MethodIMPPtr);
+  }
+  return MethodList;
 }
+
+/// Generates an IvarList.  Used in construction of a objc_class
+llvm::Value *CGObjCGNU::GenerateIvarList(llvm::LLVMFoldingBuilder &Builder,
+    std::vector<llvm::Constant*> IvarNames,
+    std::vector<llvm::Constant*> IvarTypes,
+    std::vector<llvm::Constant*> IvarOffsets) {
+  // Get the method structure type.  
+  llvm::Type *ObjCIvarTy = llvm::StructType::get(
+    PtrToInt8Ty,
+    PtrToInt8Ty,
+    IntTy,
+    NULL);
+
+  // Array of method structures
+  llvm::Type *ObjCIvarArrayTy = llvm::ArrayType::get(ObjCIvarTy,
+      IvarNames.size());
+
+  // Structure containing array and array count
+  llvm::Type *ObjCIvarListTy = llvm::StructType::get(IntTy,
+    ObjCIvarArrayTy,
+    NULL);
+
+  // Create an instance of the structure
+  llvm::Value *IvarList = Builder.CreateMalloc(ObjCIvarListTy);
+  llvm::Value *IvarArray = Builder.CreateStructGEP(IvarList, 3);
+  
+  // FIXME: This should use an iterator.  And possibly a more sensible
+  // data structure than just three vectors.
+  for(unsigned int i=0 ; i<1 ; i++) {
+    llvm::Value *IvarStruct = Builder.CreateStructGEP(IvarArray, i);
+    // Store the name
+    SetField(Builder, IvarStruct, 0, IvarNames[i]);
+    // Store the types
+    SetField(Builder, IvarStruct, 1, IvarTypes[i]);
+    // Store the fffset
+    SetField(Builder, IvarStruct, 2, IvarOffsets[i]);
+  }
+  return IvarList;
+}
+
+/// Generate a class structure
+llvm::Value *CGObjCGNU::GenerateClassStructure(
+    llvm::LLVMFoldingBuilder &Builder,
+    llvm::Value *MetaClass,
+    llvm::Value *SuperClass,
+    llvm::Value *Name,
+    llvm::Value *Version,
+    llvm::Value *InstanceSize,
+    llvm::Value *IVars,
+    llvm::Value *Methods) {
+  // Set up the class structure
+  llvm::OpaqueType *OpaqueClassTy = llvm::OpaqueType::get();
+  llvm::Type *PtrToOpaqueClassTy = llvm::PointerType::getUnqual(OpaqueClassTy);
+  llvm::Type *ClassTy = llvm::StructType::get(
+      // TODO: Should these be class names at this point?
+      PtrToOpaqueClassTy, // 0 - class_pointer
+      PtrToOpaqueClassTy, // 1 - super_class
+      PtrToInt8Ty,        // 2 - name
+      LongTy,             // 3 - version
+      LongTy,             // 4 - info
+      LongTy,             // 5 - instance_size
+      IVars->getType(),   // 6 - ivars
+      Methods->getType(), // 7 - methods
+      // These are all filled in by the runtime, so we pretend 
+      PtrTy,              // 8 - dtable
+      PtrTy,              // 9 - subclass_list
+      PtrTy,              // 10 - sibling_class
+      // FIXME: We should be filling this one in
+      PtrTy,              // 11 - protocols
+      PtrTy,              // 12 - gc_object_type
+      NULL);
+  OpaqueClassTy->refineAbstractTypeTo(ClassTy);
+  // Fill in the structure
+  llvm::Value *NewClass = Builder.CreateMalloc(ClassTy);
+  SetField(Builder, NewClass, 0, MetaClass);
+  SetField(Builder, NewClass, 1, SuperClass);
+  SetField(Builder, NewClass, 2, Name);
+  SetField(Builder, NewClass, 3, Version);
+  // TODO: info (flags)
+  SetField(Builder, NewClass, 5, InstanceSize);
+  SetField(Builder, NewClass, 6, IVars);
+  SetField(Builder, NewClass, 7, MetaClass);
+  return NewClass;
+}
+
+llvm::Function *CGObjCGNU::MethodPreamble(
+                                         const llvm::Type *ReturnTy,
+                                         const llvm::Type *SelfTy,
+                                         const llvm::Type **ArgTy,
+                                         unsigned ArgC,
+                                         bool isVarArg) {
+  std::vector<const llvm::Type*> Args;
+  Args.push_back(SelfTy);
+  Args.push_back(SelectorTy);
+  for (unsigned i=0; i<ArgC ; i++) {
+    Args.push_back(ArgTy[i]);
+  }
+  llvm::FunctionType *MethodTy = llvm::FunctionType::get(ReturnTy, Args, isVarArg);
+  llvm::Function *Method = new llvm::Function(MethodTy,
+      llvm::GlobalValue::InternalLinkage,
+      ".objc.method",
+      &TheModule);
+  // Set the names of the hidden arguments
+  llvm::Function::arg_iterator AI = Method->arg_begin();
+  AI->setName("self");
+  ++AI;
+  AI->setName("_cmd");
+  return Method;
+}
+
+clang::CodeGen::CGObjCRuntime *clang::CodeGen::CreateObjCRuntime(
+    llvm::Module &M,
+    const llvm::Type *LLVMIntType,
+    const llvm::Type *LLVMLongType) {
+  return new CGObjCGNU(M, LLVMIntType, LLVMLongType);
+}
Index: CGStmt.cpp
===================================================================
--- CGStmt.cpp	(revision 48734)
+++ CGStmt.cpp	(working copy)
@@ -332,9 +332,6 @@
   // Emit the result value, even if unused, to evalute the side effects.
   const Expr *RV = S.getRetValue();
 
-  QualType FnRetTy = CurFuncDecl->getType().getCanonicalType();
-  FnRetTy = cast<FunctionType>(FnRetTy)->getResultType();
-  
   if (FnRetTy->isVoidType()) {
     // If the function returns void, emit ret void.
     Builder.CreateRetVoid();
Index: CodeGenFunction.cpp
===================================================================
--- CodeGenFunction.cpp	(revision 48734)
+++ CodeGenFunction.cpp	(working copy)
@@ -26,7 +26,7 @@
 
 CodeGenFunction::CodeGenFunction(CodeGenModule &cgm) 
   : CGM(cgm), Target(CGM.getContext().Target), SwitchInsn(NULL), 
-    CaseRangeBlock(NULL) {}
+    CaseRangeBlock(NULL)  {}
 
 ASTContext &CodeGenFunction::getContext() const {
   return CGM.getContext();
@@ -55,13 +55,85 @@
          !T->isVoidType() && !T->isVectorType() && !T->isFunctionType();
 }
 
+/// Generate an Objective-C method.  An Objective-C method is a C function with
+/// its pointer, name, and types registered in the class struture.  
+// FIXME: This method contains a lot of code copied and pasted from
+// GenerateCode.  This should be factored out.
+void CodeGenFunction::GenerateObjCMethod(const ObjCMethodDecl *OMD) {
+  llvm::SmallVector<const llvm::Type *, 16> ParamTypes;
+  for (unsigned i=0 ; i<OMD->param_size() ; i++) {
+    ParamTypes.push_back(ConvertType(OMD->getParamDecl(i)->getType()));
+  }
+  CurFn = CGM.getObjCRuntime()->MethodPreamble(ConvertType(OMD->getResultType()),
+      llvm::PointerType::getUnqual(llvm::Type::Int32Ty),
+      ParamTypes.begin(),
+      OMD->param_size(),
+      OMD->isVariadic());
+  llvm::BasicBlock *EntryBB = new llvm::BasicBlock("entry", CurFn);
+  
+  // Create a marker to make it easy to insert allocas into the entryblock
+  // later.  Don't create this with the builder, because we don't want it
+  // folded.
+  llvm::Value *Undef = llvm::UndefValue::get(llvm::Type::Int32Ty);
+  AllocaInsertPt = new llvm::BitCastInst(Undef, llvm::Type::Int32Ty, "allocapt",
+                                         EntryBB);
 
+  FnRetTy = OMD->getResultType(); ///.getCanonicalType();
+
+  Builder.SetInsertPoint(EntryBB);
+  
+  // Emit allocs for param decls.  Give the LLVM Argument nodes names.
+  llvm::Function::arg_iterator AI = CurFn->arg_begin();
+  
+  // Name the struct return argument.
+  // FIXME: Probably should be in the runtime, or it will trample the other
+  // hidden arguments.
+  if (hasAggregateLLVMType(OMD->getResultType())) {
+    AI->setName("agg.result");
+    ++AI;
+  }
+
+  // Skip the hidden arguments.  (Typically self and _cmd)
+  ++AI; ++AI;
+
+  for (unsigned i = 0, e = OMD->getNumParams(); i != e; ++i, ++AI) {
+    assert(AI != CurFn->arg_end() && "Argument mismatch!");
+    EmitParmDecl(*OMD->getParamDecl(i), AI);
+  }
+  
+  // Emit the function body.
+  EmitStmt(OMD->getBody());
+  
+  // Emit a return for code that falls off the end. If insert point
+  // is a dummy block with no predecessors then remove the block itself.
+  llvm::BasicBlock *BB = Builder.GetInsertBlock();
+  if (isDummyBlock(BB))
+    BB->eraseFromParent();
+  else {
+    if (CurFn->getReturnType() == llvm::Type::VoidTy)
+      Builder.CreateRetVoid();
+    else
+      Builder.CreateRet(llvm::UndefValue::get(CurFn->getReturnType()));
+  }
+  assert(BreakContinueStack.empty() &&
+         "mismatched push/pop in break/continue stack!");
+  
+  // Remove the AllocaInsertPt instruction, which is just a convenience for us.
+  AllocaInsertPt->eraseFromParent();
+  AllocaInsertPt = 0;
+  // Verify that the function is well formed.
+  assert(!verifyFunction(*CurFn));
+}
+
 void CodeGenFunction::GenerateCode(const FunctionDecl *FD) {
   LLVMIntTy = ConvertType(getContext().IntTy);
   LLVMPointerWidth = static_cast<unsigned>(
     getContext().getTypeSize(getContext().getPointerType(getContext().VoidTy)));
   
   CurFuncDecl = FD;
+  FnRetTy = CurFuncDecl->getType().getCanonicalType();
+  FnRetTy = cast<FunctionType>(FnRetTy)->getResultType();
+
   CurFn = cast<llvm::Function>(CGM.GetAddrOfFunctionDecl(FD, true));
   assert(CurFn->isDeclaration() && "Function already has body?");
   
Index: CodeGenModule.cpp
===================================================================
--- CodeGenModule.cpp	(revision 48734)
+++ CodeGenModule.cpp	(working copy)
@@ -34,10 +34,16 @@
   : Context(C), Features(LO), TheModule(M), TheTargetData(TD), Diags(diags),
     Types(C, M, TD), MemCpyFn(0), MemSetFn(0), CFConstantStringClassRef(0) {
   //TODO: Make this selectable at runtime
-  Runtime = CreateObjCRuntime(M);
+  Runtime = CreateObjCRuntime(M,
+      getTypes().ConvertType(getContext().IntTy),
+      getTypes().ConvertType(getContext().LongTy));
 }
 
 CodeGenModule::~CodeGenModule() {
+  llvm::Function *ObjCInitFunction = Runtime->ModuleInitFunction();
+  if (ObjCInitFunction) {
+    AddGlobalCtor(ObjCInitFunction);
+  }
   EmitGlobalCtors();
   delete Runtime;
 }
@@ -70,7 +76,10 @@
   GlobalCtors.push_back(Ctor);
 }
 
+/// EmitGlobalCtors - Generates the array of contsturctor functions to be
+/// called on module load, if any have been registered with AddGlobalCtor.
 void CodeGenModule::EmitGlobalCtors() {
+  if (GlobalCtors.empty()) return;
   // Get the type of @llvm.global_ctors
   std::vector<const llvm::Type*> CtorFields;
   CtorFields.push_back(llvm::IntegerType::get(32));
@@ -114,6 +123,8 @@
 
 }
 
+
+
 /// ReplaceMapValuesWith - This is a really slow and bad function that
 /// searches for any entries in GlobalDeclMap that point to OldVal, changing
 /// them to point to NewVal.  This is badbadbad, FIXME!
@@ -263,6 +274,12 @@
 }
 
 
+void CodeGenModule::EmitObjCMethod(const ObjCMethodDecl *OMD) {
+  // If this is not a prototype, emit the body.
+  if (OMD->getBody())
+    CodeGenFunction(*this).GenerateObjCMethod(OMD);
+}
+
 void CodeGenModule::EmitFunction(const FunctionDecl *FD) {
   // If this is not a prototype, emit the body.
   if (FD->getBody())
Index: CGExprScalar.cpp
===================================================================
--- CGExprScalar.cpp	(revision 48734)
+++ CGExprScalar.cpp	(working copy)
@@ -19,6 +19,7 @@
 #include "llvm/GlobalVariable.h"
 #include "llvm/Intrinsics.h"
 #include "llvm/Support/Compiler.h"
+#include "llvm/ValueSymbolTable.h"
 #include <cstdarg>
 
 using namespace clang;
@@ -126,6 +127,7 @@
     return EmitLoadOfLValue(E);
   }
   Value *VisitObjCMessageExpr(ObjCMessageExpr *E);
+  Value *VisitObjCIvarRefExpr(ObjCIvarRefExpr *E);
   Value *VisitArraySubscriptExpr(ArraySubscriptExpr *E);
   Value *VisitMemberExpr(Expr *E)           { return EmitLoadOfLValue(E); }
   Value *VisitOCUVectorElementExpr(Expr *E) { return EmitLoadOfLValue(E); }
@@ -449,6 +451,38 @@
   return llvm::UndefValue::get(CGF.ConvertType(E->getType()));
 }
 
+Value *ScalarExprEmitter::VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
+  // Objective-C objects are traditionally C structures with their layout
+  // defined at compile-time.  In some implementations, their layout is not
+  // defined until run time in order to allow instance variables to be added to
+  // a class without recompiling all of the subclasses.  If this is the case
+  // then the CGObjCRuntime subclass must return true to LateBoundIvars and
+  // implement the lookup itself.
+  if(CGF.CGM.getObjCRuntime()->LateBoundIVars()) {
+    assert(0 && "FIXME: Implement support for late-bound instance variables");
+    return 0; // Not reached.
+  }
+  else {
+    // Get a structure type for the object
+    QualType ExprTy = E->getBase()->getType();
+    const llvm::Type *ObjectType = ConvertType(ExprTy);
+    //TODO:  Add a special case for isa (index 0)
+    // Work out which index the ivar is
+    ObjCIvarDecl *Decl = E->getDecl();
+    unsigned Index = CGF.CGM.getTypes().getLLVMFieldNo(ExprTy, Decl);
+    
+    // Get object pointer
+    llvm::Value * Object = CGF.EmitLValue(E->getBase()).getAddress();
+    // Coerce object pointer to correct type.
+    if (Object->getType() != ObjectType) {
+      Object = Builder.CreateBitCast(Object, ObjectType);
+    }
+    // Get the correct element
+    llvm::Value * Element = Builder.CreateStructGEP(Object, Index);
+    Element = Builder.CreateLoad(Element, Decl->getName());
+    return Element;
+  }
+}
 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
@@ -481,11 +515,13 @@
   // Get the selector string
   std::string SelStr = E->getSelector().getName();
   llvm::Constant *Selector = CGF.CGM.GetAddrOfConstantString(SelStr);
-  ConvertType(E->getType());
+
+  llvm::Value *SelPtr = Builder.CreateStructGEP(Selector, 0);
   return Runtime->generateMessageSend(Builder,
       ConvertType(E->getType()),
+      CGF.CurFn->getValueSymbolTable().lookup("self"),
       Receiver,
-      Selector,
+      SelPtr,
       &Args[0],
       Args.size());
 }
Index: CodeGenFunction.h
===================================================================
--- CodeGenFunction.h	(revision 48734)
+++ CodeGenFunction.h	(working copy)
@@ -14,6 +14,7 @@
 #ifndef CLANG_CODEGEN_CODEGENFUNCTION_H
 #define CLANG_CODEGEN_CODEGENFUNCTION_H
 
+#include "clang/AST/Type.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/Support/LLVMBuilder.h"
@@ -27,8 +28,8 @@
   class ASTContext;
   class Decl;
   class FunctionDecl;
+  class ObjCMethodDecl;
   class TargetInfo;
-  class QualType;
   class FunctionTypeProto;
   
   class Stmt;
@@ -66,6 +67,7 @@
   class ChooseExpr;
   class PreDefinedExpr;
   class ObjCStringLiteral;
+  class ObjCIvarRefExpr;
   class MemberExpr;
 
   class BlockVarDecl;
@@ -245,6 +247,7 @@
   llvm::LLVMFoldingBuilder Builder;
   
   const FunctionDecl *CurFuncDecl;
+  QualType FnRetTy;
   llvm::Function *CurFn;
 
   /// AllocaInsertPoint - This is an instruction in the entry block before which
@@ -286,6 +289,7 @@
   
   ASTContext &getContext() const;
 
+  void GenerateObjCMethod(const ObjCMethodDecl *OMD);
   void GenerateCode(const FunctionDecl *FD);
   
   const llvm::Type *ConvertType(QualType T);
@@ -422,7 +426,8 @@
 
   LValue EmitLValueForField(llvm::Value* Base, FieldDecl* Field,
                             bool isUnion);
-    
+      
+  LValue EmitObjCIvarRefLValue(const ObjCIvarRefExpr *E);
   //===--------------------------------------------------------------------===//
   //                         Scalar Expression Emission
   //===--------------------------------------------------------------------===//
Index: CodeGenModule.h
===================================================================
--- CodeGenModule.h	(revision 48734)
+++ CodeGenModule.h	(working copy)
@@ -30,6 +30,7 @@
 namespace clang {
   class ASTContext;
   class FunctionDecl;
+  class ObjCMethodDecl;
   class Decl;
   class Expr;
   class Stmt;
@@ -100,6 +101,7 @@
   void AddGlobalCtor(llvm::Function * Ctor);
   void EmitGlobalCtors(void);
 
+  void EmitObjCMethod(const ObjCMethodDecl *OMD);
   void EmitFunction(const FunctionDecl *FD);
   void EmitGlobalVar(const FileVarDecl *D);
   void EmitGlobalVarDeclarator(const FileVarDecl *D);
Index: CGExpr.cpp
===================================================================
--- CGExpr.cpp	(revision 48734)
+++ CGExpr.cpp	(working copy)
@@ -82,6 +82,7 @@
 LValue CodeGenFunction::EmitLValue(const Expr *E) {
   switch (E->getStmtClass()) {
   default: {
+             printf("Statement class: %d\n", E->getStmtClass());
     WarnUnsupported(E, "l-value expression");
     llvm::Type *Ty = llvm::PointerType::getUnqual(ConvertType(E->getType()));
     return LValue::MakeAddr(llvm::UndefValue::get(Ty));
@@ -94,6 +95,9 @@
     return EmitPreDefinedLValue(cast<PreDefinedExpr>(E));
   case Expr::StringLiteralClass:
     return EmitStringLiteralLValue(cast<StringLiteral>(E));
+
+  case Expr::ObjCIvarRefExprClass: 
+    return EmitObjCIvarRefLValue(cast<ObjCIvarRefExpr>(E));
     
   case Expr::UnaryOperatorClass: 
     return EmitUnaryOpLValue(cast<UnaryOperator>(E));
@@ -341,6 +345,17 @@
       return LValue::MakeAddr(CGM.GetAddrOfGlobalVar(VD, false));
     else {
       llvm::Value *V = LocalDeclMap[D];
+      // Check if it's an implicit argument
+      // TODO: Other runtimes may set non-argument hidden variables
+      if (!V) {
+        std::string VarName(D->getName());
+        llvm::Function::arg_iterator AI = CurFn->arg_begin();
+        do {
+          if(VarName == AI->getName()) {
+            return LValue::MakeAddr(AI);
+          }
+        } while(++AI);
+      }
       assert(V && "BlockVarDecl not entered in LocalDeclMap?");
       return LValue::MakeAddr(V);
     }
@@ -555,6 +570,33 @@
   return LValue::MakeAddr(RV.getAggregateAddr());
 }
 
+LValue CodeGenFunction::EmitObjCIvarRefLValue(const ObjCIvarRefExpr *E) {
+  if(CGM.getObjCRuntime()->LateBoundIVars()) {
+    assert(0 && "FIXME: Implement support for late-bound instance variables");
+    return LValue(); // Not reached.
+  }
+  else {
+    // Get a structure type for the object
+    QualType ExprTy = E->getBase()->getType();
+    const llvm::Type *ObjectType = ConvertType(ExprTy);
+    //TODO:  Add a special case for isa (index 0)
+    // Work out which index the ivar is
+    const ObjCIvarDecl *Decl = E->getDecl();
+    unsigned Index = CGM.getTypes().getLLVMFieldNo(ExprTy, Decl);
+    
+    // Get object pointer
+    llvm::Value * Object = EmitLValue(E->getBase()).getAddress();
+    // Coerce object pointer to correct type.
+    if (Object->getType() != ObjectType) {
+      Object = Builder.CreateBitCast(Object, ObjectType);
+    }
+    // Get the correct element
+    llvm::Value * Element = Builder.CreateStructGEP(Object, Index, Decl->getName());
+  //  Element = Builder.CreateLoad(Element);
+    return LValue::MakeAddr(Element);
+  }
+}
+
 RValue CodeGenFunction::EmitCallExpr(llvm::Value *Callee, QualType FnType, 
                                      Expr *const *ArgExprs, unsigned NumArgs) {
   // The callee type will always be a pointer to function type, get the function
Index: CodeGenTypes.cpp
===================================================================
--- CodeGenTypes.cpp	(revision 48734)
+++ CodeGenTypes.cpp	(working copy)
@@ -144,8 +144,22 @@
   cast<llvm::OpaqueType>(OpaqueHolder.get())->refineAbstractTypeTo(NT);
 }
 
+/// Produces a vector containing the all of the instance variables in an
+/// Objective-C object, in the order that they appear.  Used to create LLVM
+/// structures corresponding to Objective-C objects.
+void CodeGenTypes::CollectObjCIvarTypes(ObjCInterfaceDecl *ObjCClass,
+    std::vector<const llvm::Type*> &IvarTypes) {
+  ObjCInterfaceDecl *SuperClass = ObjCClass->getSuperClass();
+  if(SuperClass) {
+    CollectObjCIvarTypes(SuperClass, IvarTypes);
+  }
+  for(ObjCInterfaceDecl::ivar_iterator ivar=ObjCClass->ivar_begin() ;
+      ivar != ObjCClass->ivar_end() ;
+      ivar++) {
+    IvarTypes.push_back(ConvertType((*ivar)->getType()));
+  }
+}
 
-
 const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {
   const clang::Type &Ty = *T.getCanonicalType();
   
@@ -263,9 +277,21 @@
   case Type::ASQual:
     return ConvertType(QualType(cast<ASQualType>(Ty).getBaseType(), 0));
 
-  case Type::ObjCInterface:
-    assert(0 && "FIXME: add missing functionality here");
-    break;
+  case Type::ObjCInterface: {
+    // Warning: Use of this is strongly discouraged.  Late binding of instance
+    // variables is supported on some runtimes and so using static binding can
+    // break code when libraries are updated.  Only use this if you have
+    // previously checked that the ObjCRuntime subclass in use does not support
+    // late-bound ivars.
+    ObjCInterfaceType OIT = cast<ObjCInterfaceType>(Ty);
+    std::vector<const llvm::Type*> IvarTypes;
+    // Pointer to the class.  This is just a placeholder.  Operations that
+    // actually use the isa pointer should cast it to the Class type provided
+    // by the runtime.
+    IvarTypes.push_back(llvm::PointerType::getUnqual(llvm::Type::Int8Ty));
+    CollectObjCIvarTypes(OIT.getDecl(), IvarTypes);
+    return llvm::StructType::get(IvarTypes);
+  }
       
   case Type::ObjCQualifiedInterface:
     assert(0 && "FIXME: add missing functionality here");
@@ -399,6 +425,37 @@
   return I->second;
 }
 
+unsigned CodeGenTypes::getLLVMFieldNo(QualType ObjectTy, const ObjCIvarDecl *Decl) {
+  unsigned Index = 1;
+  bool found = false;
+  const clang::Type &Ty = *ObjectTy.getCanonicalType();
+  const QualType OTy = cast<PointerType>(Ty).getPointeeType();
+  ObjCInterfaceDecl * Class = cast<ObjCInterfaceType>(*OTy).getDecl();
+  // Find the Ivar:
+  while(Class) {
+    if(found) {
+      Index += Class->ivar_size();
+    }
+    else {
+      for(ObjCInterfaceDecl::ivar_iterator ivar = Class->ivar_end() ;
+          ivar != Class->ivar_begin() ;
+          ivar--) {
+        if(!found) {
+          if(*ivar == Decl) {
+            found = true;
+            Index++;
+          }
+        }
+        else {
+          Index++;
+        }
+      }
+    }
+    Class = Class->getSuperClass();
+  }
+  return Index;
+}
+
 /// addFieldInfo - Assign field number to field FD.
 void CodeGenTypes::addFieldInfo(const FieldDecl *FD, unsigned No) {
   FieldInfo[FD] = No;
Index: CGObjCEtoile.cpp
===================================================================
--- CGObjCEtoile.cpp	(revision 0)
+++ CGObjCEtoile.cpp	(revision 0)
@@ -0,0 +1,250 @@
+//===------- CGObjCEtoile.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 Etoile runtime.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CGObjCRuntime.h"
+#include "llvm/Module.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/LLVMBuilder.h"
+#include "llvm/ADT/SmallVector.h"
+
+
+clang::CodeGen::CGObjCRuntime::~CGObjCRuntime() {}
+
+namespace {
+class CGObjCEtoile : public clang::CodeGen::CGObjCRuntime {
+private:
+  llvm::Module &TheModule;
+  const llvm::Type *SelectorTy;
+  const llvm::PointerType *PtrToInt8Ty;
+  const llvm::Type *IMPTy;
+  const llvm::Type *IntTy;
+  const llvm::Type *PtrTy;
+  const llvm::Type *LongTy;
+  const llvm::Type *PtrToIntTy;
+  const llvm::Type *IdTy;
+  const llvm::Type *CallTy;
+  const llvm::Type *SlotTy;
+  const llvm::Type *LookupFunctionTy;
+public:
+  CGObjCEtoile(llvm::Module &Mp,
+    const llvm::Type *LLVMIntType,
+    const llvm::Type *LLVMLongType);
+  virtual llvm::Value *generateMessageSend(llvm::LLVMFoldingBuilder &Builder,
+                                           const llvm::Type *ReturnTy,
+                                           llvm::Value *Sender,
+                                           llvm::Value *Receiver,
+                                           llvm::Value *Selector,
+                                           llvm::Value** ArgV,
+                                           unsigned ArgC);
+  llvm::Value *getSelector(llvm::LLVMFoldingBuilder &Builder,
+      llvm::Value *SelName,
+      llvm::Value *SelTypes);
+  virtual llvm::Function *MethodPreamble(const llvm::Type *ReturnTy,
+                                         const llvm::Type *SelfTy,
+                                         const llvm::Type **ArgTy,
+                                         unsigned ArgC,
+                                         bool isVarArg);
+};
+} // end anonymous namespace
+
+CGObjCEtoile::CGObjCEtoile(llvm::Module &M,
+    const llvm::Type *LLVMIntType,
+    const llvm::Type *LLVMLongType) : 
+  TheModule(M),
+  IntTy(LLVMIntType),
+  LongTy(LLVMLongType)
+{
+  // C string type.  Used in lots of places.
+  PtrToInt8Ty = 
+    llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
+  // Get the selector Type.
+  SelectorTy = llvm::Type::Int32Ty;
+  PtrToIntTy = llvm::PointerType::getUnqual(IntTy);
+  PtrTy = llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
+ 
+  // Object type
+  llvm::OpaqueType *OpaqueObjTy = llvm::OpaqueType::get();
+  llvm::Type *OpaqueIdTy = llvm::PointerType::getUnqual(OpaqueObjTy);
+  IdTy = llvm::PointerType::getUnqual(llvm::StructType::get(OpaqueIdTy, NULL));
+  OpaqueObjTy->refineAbstractTypeTo(IdTy);
+
+  // Call structure type.
+  llvm::OpaqueType *OpaqueSlotTy = llvm::OpaqueType::get();
+  CallTy = llvm::StructType::get(
+      llvm::PointerType::getUnqual(OpaqueSlotTy),
+      SelectorTy,
+      IdTy,
+      NULL);
+  //CallTy = llvm::PointerType::getUnqual(CallTy);
+
+  // IMP type
+  std::vector<const llvm::Type*> IMPArgs;
+  IMPArgs.push_back(IdTy);
+  IMPArgs.push_back(llvm::PointerType::getUnqual(CallTy));
+  IMPTy = llvm::FunctionType::get(IdTy, IMPArgs, true);
+
+  // Slot type
+  SlotTy = llvm::StructType::get(IntTy,
+      IMPTy,
+      PtrToInt8Ty,
+      PtrToInt8Ty,
+      llvm::Type::Int32Ty,
+      NULL);
+  OpaqueSlotTy->refineAbstractTypeTo(SlotTy);
+  SlotTy = llvm::PointerType::getUnqual(SlotTy);
+
+  // Lookup function type
+  std::vector<const llvm::Type*> LookupFunctionArgs;
+  LookupFunctionArgs.push_back(llvm::PointerType::getUnqual(IdTy));
+  LookupFunctionArgs.push_back(IdTy);
+  LookupFunctionArgs.push_back(SelectorTy);
+  LookupFunctionArgs.push_back(IdTy);
+  LookupFunctionTy = 
+    llvm::FunctionType::get(SlotTy, LookupFunctionArgs, false);
+  LookupFunctionTy = llvm::PointerType::getUnqual(LookupFunctionTy);
+
+}
+
+/// Looks up the selector for the specified name / type pair.
+llvm::Value *CGObjCEtoile::getSelector(llvm::LLVMFoldingBuilder &Builder,
+    llvm::Value *SelName,
+    llvm::Value *SelTypes)
+{
+  // Look up the selector.
+  if(SelTypes == 0) {
+    SelTypes = llvm::ConstantPointerNull::get(PtrToInt8Ty);
+  }
+  llvm::Constant *SelFunction = 
+    TheModule.getOrInsertFunction("lookup_typed_selector",
+        SelectorTy,
+        PtrToInt8Ty,
+        PtrToInt8Ty,
+        NULL);
+  llvm::SmallVector<llvm::Value*, 2> Args;
+  Args.push_back(SelName);
+  Args.push_back(SelTypes);
+  return Builder.CreateCall(SelFunction, Args.begin(), Args.end());
+}
+
+static void SetField(llvm::LLVMFoldingBuilder &Builder,
+                     llvm::Value *Structure, 
+                     unsigned Index, 
+                     llvm::Value *Value) {
+    llvm::Value *element_ptr = Builder.CreateStructGEP(Structure, Index);
+    Builder.CreateStore(Value, element_ptr);
+}
+// Generate code for a message send expression on the Etoile runtime.
+// BIG FAT WARNING: Much of this code will need factoring out later.
+llvm::Value *CGObjCEtoile::generateMessageSend(
+                                            llvm::LLVMFoldingBuilder &Builder,
+                                            const llvm::Type *ReturnTy,
+                                            llvm::Value *Sender,
+                                            llvm::Value *Receiver,
+                                            llvm::Value *Selector,
+                                            llvm::Value** ArgV,
+                                            unsigned ArgC) {
+  // FIXME: Selectors should be statically cached, not looked up on every call.
+  llvm::Value *cmd = getSelector(Builder, Selector, 0);
+  // TODO: [Polymorphic] inline caching
+
+  // Get the lookup function for this object:
+  llvm::Value *ObjAddr = Builder.CreateBitCast(Receiver, PtrToInt8Ty);
+  llvm::Value *FunctionOffset = new llvm::GlobalVariable(llvm::Type::Int32Ty,
+      false,
+      llvm::GlobalValue::ExternalLinkage,
+      0,
+      "lookup_offset",
+      &TheModule);
+  FunctionOffset = Builder.CreateLoad(FunctionOffset);
+  llvm::Value *Tag = Builder.CreateGEP(ObjAddr, FunctionOffset);
+  llvm::Value *Lookup = Builder.CreateBitCast(Tag, LookupFunctionTy);
+
+  // TODO: Remove this when the caller is providing sensible sender info
+  if(Sender == 0) {
+    Sender = llvm::ConstantPointerNull::get((llvm::PointerType*)IdTy);
+  }
+  Receiver = Builder.CreateBitCast(Receiver, IdTy);
+  llvm::Value *ReceiverAddr = Builder.CreateAlloca(IdTy);
+  Builder.CreateStore(Receiver, ReceiverAddr);
+  // Look up the method implementation.
+  llvm::SmallVector<llvm::Value*, 4> LookupArgs;
+  LookupArgs.push_back(ReceiverAddr);
+  LookupArgs.push_back(Receiver);
+  LookupArgs.push_back(cmd);
+  LookupArgs.push_back(Sender);
+  llvm::Value *Slot = Builder.CreateCall(Lookup,
+      LookupArgs.begin(),
+      LookupArgs.end());
+  
+  // Create the call structure
+  llvm::Value *Call = Builder.CreateAlloca(CallTy);
+  SetField(Builder, Call, 0, Slot);
+  SetField(Builder, Call, 1, cmd);
+  SetField(Builder, Call, 2, Sender);
+
+  // Get the IMP from the slot and call it
+  // TODO: Property load / store optimisations
+  llvm::Value *IMP = Builder.CreateStructGEP(Slot, 1);
+  // If the return type of the IMP is wrong, cast it so it isn't.
+  if(ReturnTy != IdTy) {
+    std::vector<const llvm::Type*> IMPArgs;
+    IMPArgs.push_back(IdTy);
+    IMPArgs.push_back(llvm::PointerType::getUnqual(CallTy));
+    llvm::Type *NewIMPTy = llvm::FunctionType::get(ReturnTy, IMPArgs, true);
+    IMP = Builder.CreateBitCast(IMP, llvm::PointerType::getUnqual(NewIMPTy));
+  }
+  llvm::SmallVector<llvm::Value*, 16> Args;
+  Args.push_back(Receiver);
+  Args.push_back(Call);
+  Args.insert(Args.end(), ArgV, ArgV+ArgC);
+  return Builder.CreateCall(IMP, Args.begin(), Args.end());
+}
+
+/// Generates an LLVM Function object corresponding to the Objective-C method,
+/// including the implicit arguments.
+llvm::Function *CGObjCEtoile::MethodPreamble(
+                                         const llvm::Type *ReturnTy,
+                                         const llvm::Type *SelfTy,
+                                         const llvm::Type **ArgTy,
+                                         unsigned ArgC,
+                                         bool isVarArg) {
+  std::vector<const llvm::Type*> Args;
+  //Args.push_back(SelfTy);
+  Args.push_back(IdTy);
+  Args.push_back(llvm::PointerType::getUnqual(CallTy));
+  for (unsigned i=0; i<ArgC ; i++) {
+    Args.push_back(ArgTy[i]);
+  }
+  llvm::FunctionType *MethodTy = 
+    llvm::FunctionType::get(ReturnTy, Args, isVarArg);
+  llvm::Function *Method = new llvm::Function(MethodTy,
+      llvm::GlobalValue::InternalLinkage,
+      ".objc.method",
+      &TheModule);
+  //llvm::BasicBlock *EntryBB = new llvm::BasicBlock("entry", Method);
+  // Set the names of the hidden arguments
+  llvm::Function::arg_iterator AI = Method->arg_begin();
+  AI[0].setName("self");
+  AI[1].setName("_call");
+  // FIXME: Should create the _cmd variable as _call->selector
+  return Method;
+}
Index: ModuleBuilder.cpp
===================================================================
--- ModuleBuilder.cpp	(revision 48734)
+++ ModuleBuilder.cpp	(working copy)
@@ -63,6 +63,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<ObjCCategoryDecl>(D)){
+        //Only used for typechecking.
+      } else if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)){
+        Builder->EmitObjCMethod(OMD);
       } else if (FileVarDecl *FVD = dyn_cast<FileVarDecl>(D)) {
         Builder->EmitGlobalVarDeclarator(FVD);
       } else if (LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(D)) {
