[cfe-commits] r48969 - in /cfe/trunk/lib/CodeGen: CGExpr.cpp CGExprScalar.cpp CGObjC.cpp CGObjCGNU.cpp CGObjCRuntime.h CGStmt.cpp CodeGenFunction.cpp CodeGenFunction.h CodeGenModule.cpp CodeGenModule.h CodeGenTypes.cpp CodeGenTypes.h ModuleBuilder.cpp

Chris Lattner sabre at nondot.org
Sun Mar 30 16:03:08 PDT 2008


Author: lattner
Date: Sun Mar 30 18:03:07 2008
New Revision: 48969

URL: http://llvm.org/viewvc/llvm-project?rev=48969&view=rev
Log:
Add initial support for objc codegen for methods, ivars, and the
etoile runtime, patch by David Chisnall!

Modified:
    cfe/trunk/lib/CodeGen/CGExpr.cpp
    cfe/trunk/lib/CodeGen/CGExprScalar.cpp
    cfe/trunk/lib/CodeGen/CGObjC.cpp
    cfe/trunk/lib/CodeGen/CGObjCGNU.cpp
    cfe/trunk/lib/CodeGen/CGObjCRuntime.h
    cfe/trunk/lib/CodeGen/CGStmt.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.h
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.h
    cfe/trunk/lib/CodeGen/CodeGenTypes.cpp
    cfe/trunk/lib/CodeGen/CodeGenTypes.h
    cfe/trunk/lib/CodeGen/ModuleBuilder.cpp

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Sun Mar 30 18:03:07 2008
@@ -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));
@@ -555,6 +559,41 @@
   return LValue::MakeAddr(RV.getAggregateAddr());
 }
 
+LValue CodeGenFunction::EmitObjCIvarRefLValue(const 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(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(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

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Sun Mar 30 18:03:07 2008
@@ -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,10 @@
   return llvm::UndefValue::get(CGF.ConvertType(E->getType()));
 }
 
+Value *ScalarExprEmitter::VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
+  return Builder.CreateLoad(CGF.EmitObjCIvarRefLValue(E).getAddress());
+}
+
 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 +487,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());
 }

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjC.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjC.cpp Sun Mar 30 18:03:07 2008
@@ -23,3 +23,4 @@
   return CGM.GetAddrOfConstantCFString(S);
 }
 
+

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCGNU.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCGNU.cpp Sun Mar 30 18:03:07 2008
@@ -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
 //
@@ -17,60 +17,124 @@
 #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);
+  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.
+  const llvm::Type *SelStructTy = llvm::StructType::get(
+      PtrToInt8Ty,
+      PtrToInt8Ty,
+      NULL);
+  SelectorTy = llvm::PointerType::getUnqual(SelStructTy);
+  PtrToIntTy = llvm::PointerType::getUnqual(IntTy);
+  PtrTy = PtrToInt8Ty;
+ 
+  // Object type
+  llvm::PATypeHolder OpaqueObjTy = llvm::OpaqueType::get();
+  llvm::Type *OpaqueIdTy = llvm::PointerType::getUnqual(OpaqueObjTy);
+  IdTy = llvm::StructType::get(OpaqueIdTy, NULL);
+  llvm::cast<llvm::OpaqueType>(OpaqueObjTy.get())->refineAbstractTypeTo(IdTy);
+  IdTy = llvm::cast<llvm::StructType>(OpaqueObjTy.get());
+  IdTy = llvm::PointerType::getUnqual(IdTy);
+ 
+  // IMP type
+  std::vector<const llvm::Type*> IMPArgs;
+  IMPArgs.push_back(IdTy);
+  IMPArgs.push_back(SelectorTy);
+  IMPTy = llvm::FunctionType::get(IdTy, IMPArgs, true);
+
+}
+
+/// 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::Value *Args[] = { SelName, SelTypes };
+    cmd = Builder.CreateCall(SelFunction, Args, Args+2);
+  }
+  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);
-
-  // 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);
+  llvm::Value *cmd = getSelector(Builder, Selector, 0);
 
   // 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 +143,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 +156,35 @@
   return Builder.CreateCall(imp, lookupArgs.begin(), lookupArgs.end());
 }
 
-CGObjCRuntime * clang::CodeGen::CreateObjCRuntime(llvm::Module &M) {
-  return new CGObjCGNU(M);
+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);
+  Args.insert(Args.end(), ArgTy, ArgTy+ArgC);
+
+  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);
 }

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCRuntime.h (original)
+++ cfe/trunk/lib/CodeGen/CGObjCRuntime.h Sun Mar 30 18:03:07 2008
@@ -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

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CGStmt.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGStmt.cpp Sun Mar 30 18:03:07 2008
@@ -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();

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Sun Mar 30 18:03:07 2008
@@ -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,6 +55,80 @@
          !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();
+
+  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;
+  }
+
+  // Add implicit parameters to the decl map.
+  // TODO: Add something to AST to let the runtime specify the names and types
+  // of these.
+  llvm::Value *&DMEntry = LocalDeclMap[&(*OMD->getSelfDecl())];
+  DMEntry = AI;
+  ++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) && "Generated method is not well formed.");
+}
 
 void CodeGenFunction::GenerateCode(const FunctionDecl *FD) {
   LLVMIntTy = ConvertType(getContext().IntTy);
@@ -62,6 +136,9 @@
     getContext().getTypeSize(getContext().getPointerType(getContext().VoidTy)));
   
   CurFuncDecl = FD;
+  FnRetTy = CurFuncDecl->getType()->getAsFunctionType()->getResultType();
+
+
   CurFn = cast<llvm::Function>(CGM.GetAddrOfFunctionDecl(FD, true));
   assert(CurFn->isDeclaration() && "Function already has body?");
   
@@ -144,7 +221,7 @@
   AllocaInsertPt = 0;
   
   // Verify that the function is well formed.
-  assert(!verifyFunction(*CurFn));
+  assert(!verifyFunction(*CurFn) && "Generated function is not well formed.");
 }
 
 /// isDummyBlock - Return true if BB is an empty basic block

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Sun Mar 30 18:03:07 2008
@@ -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
   //===--------------------------------------------------------------------===//

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Sun Mar 30 18:03:07 2008
@@ -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())

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.h Sun Mar 30 18:03:07 2008
@@ -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);

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenTypes.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenTypes.cpp Sun Mar 30 18:03:07 2008
@@ -144,7 +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()));
+    ObjCIvarInfo[*ivar] = IvarTypes.size() - 1;
+  }
+}
 
 const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {
   const clang::Type &Ty = *T.getCanonicalType();
@@ -263,9 +278,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 +426,13 @@
   return I->second;
 }
 
+unsigned CodeGenTypes::getLLVMFieldNo(const ObjCIvarDecl *OID) {
+  llvm::DenseMap<const ObjCIvarDecl*, unsigned>::iterator
+    I = ObjCIvarInfo.find(OID);
+  assert (I != ObjCIvarInfo.end()  && "Unable to find field info");
+  return I->second;
+}
+
 /// addFieldInfo - Assign field number to field FD.
 void CodeGenTypes::addFieldInfo(const FieldDecl *FD, unsigned No) {
   FieldInfo[FD] = No;

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenTypes.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenTypes.h Sun Mar 30 18:03:07 2008
@@ -34,6 +34,8 @@
   class FunctionTypeProto;
   class FieldDecl;
   class RecordDecl;
+  class ObjCInterfaceDecl;
+  class ObjCIvarDecl;
 
 namespace CodeGen {
   class CodeGenTypes;
@@ -86,6 +88,7 @@
   /// FieldInfo - This maps struct field with corresponding llvm struct type
   /// field no. This info is populated by record organizer.
   llvm::DenseMap<const FieldDecl *, unsigned> FieldInfo;
+  llvm::DenseMap<const ObjCIvarDecl *, unsigned> ObjCIvarInfo;
 
 public:
   class BitFieldInfo {
@@ -128,12 +131,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(const ObjCIvarDecl *OID);
     
   
   /// UpdateCompletedType - When we find the full definition for a TagDecl,

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

==============================================================================
--- cfe/trunk/lib/CodeGen/ModuleBuilder.cpp (original)
+++ cfe/trunk/lib/CodeGen/ModuleBuilder.cpp Sun Mar 30 18:03:07 2008
@@ -65,6 +65,10 @@
         Builder->EmitFunction(FD);
       } else if (FileVarDecl *FVD = dyn_cast<FileVarDecl>(D)) {
         Builder->EmitGlobalVarDeclarator(FVD);
+      } else if (isa<ObjCClassDecl>(D) || isa<ObjCCategoryDecl>(D)) {
+        // Forward declaration.  Only used for type checking.
+      } else if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)){
+        Builder->EmitObjCMethod(OMD);
       } else if (LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(D)) {
         if (LSD->getLanguage() == LinkageSpecDecl::lang_cxx)
           Builder->WarnUnsupported(LSD, "linkage spec");





More information about the cfe-commits mailing list