]> granicus.if.org Git - clang/commitdiff
Add codegen support for ObjC message expressions with the GNU runtime.
authorChris Lattner <sabre@nondot.org>
Sat, 1 Mar 2008 08:45:05 +0000 (08:45 +0000)
committerChris Lattner <sabre@nondot.org>
Sat, 1 Mar 2008 08:45:05 +0000 (08:45 +0000)
Patch by David Chisnall!

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@47789 91177308-0d34-0410-b5e6-96231b3b80d8

CodeGen/CGExprConstant.cpp
CodeGen/CGExprScalar.cpp
CodeGen/CodeGenModule.cpp
CodeGen/CodeGenModule.h
clang.xcodeproj/project.pbxproj

index ec16b16a9d49f9fd6f0c63f9d3369ffecfab8c7b..30180c17744ad9c1b9c0d48d4d4c7c8f88570e31 100644 (file)
@@ -200,6 +200,9 @@ public:
     
     // 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 85831d5dd3616aa060b088d66abb1a081663ff50..52b022b6611efcac1d5676ea2ce4116f4bb51fcf 100644 (file)
@@ -41,9 +41,14 @@ class VISIBILITY_HIDDEN ScalarExprEmitter
   : 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 @@ public:
       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,47 @@ Value *ScalarExprEmitter::VisitExpr(Expr *E) {
   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);
+  ConvertType(E->getType());
+  return Runtime->generateMessageSend(Builder,
+      ConvertType(E->getType()),
+      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 e3181337bfd803c70a943bec7fe36102ee359a43..5e63a80c94aab29efdb88005f3c487cc3aca827b 100644 (file)
@@ -31,7 +31,14 @@ CodeGenModule::CodeGenModule(ASTContext &C, const LangOptions &LO,
                              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 = CreateObjCRuntime(M);
+}
+
+CodeGenModule::~CodeGenModule() {
+  delete Runtime;
+}
 
 /// WarnUnsupported - Print out a warning that codegen doesn't support the
 /// specified stmt yet.
index 7863f7bebd4d1f36dbf97994bd4f51561c2110e2..80ce3076d41ed054e5cc88f256a195877848c938 100644 (file)
@@ -15,6 +15,7 @@
 #define CLANG_CODEGEN_CODEGENMODULE_H
 
 #include "CodeGenTypes.h"
+#include "CGObjCRuntime.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/StringMap.h"
 
@@ -52,6 +53,7 @@ class CodeGenModule {
   const llvm::TargetData &TheTargetData;
   Diagnostic &Diags;
   CodeGenTypes Types;
+  CGObjCRuntime *Runtime;
 
   llvm::Function *MemCpyFn;
   llvm::Function *MemSetFn;
@@ -65,7 +67,9 @@ class CodeGenModule {
 public:
   CodeGenModule(ASTContext &C, const LangOptions &Features, llvm::Module &M, 
                 const llvm::TargetData &TD, Diagnostic &Diags);
+  ~CodeGenModule();
   
+  CGObjCRuntime *getObjCRuntime() { return Runtime; }
   ASTContext &getContext() const { return Context; }
   const LangOptions &getLangOptions() const { return Features; }
   llvm::Module &getModule() const { return TheModule; }
index dcbf2289f594eab07f3134d2ff930b39992322eb..e9c86ca82740bd3b86b1f9ea6b9c4f3b8c168ac2 100644 (file)
@@ -62,6 +62,7 @@
                DE3461270AFE68BE00DBC861 /* MinimalAction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE3461260AFE68BE00DBC861 /* MinimalAction.cpp */; };
                DE34621D0AFEB19B00DBC861 /* StmtPrinter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE34621C0AFEB19B00DBC861 /* StmtPrinter.cpp */; };
                DE3464220B03040900DBC861 /* Type.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE3464210B03040900DBC861 /* Type.h */; };
+               DE38CD500D794D0100A273B6 /* CGObjCGNU.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE38CD4F0D794D0100A273B6 /* CGObjCGNU.cpp */; };
                DE3985790CB8ADC800223765 /* ASTConsumers.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE3985780CB8ADC800223765 /* ASTConsumers.h */; };
                DE39857B0CB8ADCB00223765 /* ASTConsumers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE39857A0CB8ADCB00223765 /* ASTConsumers.cpp */; };
                DE3986F00CB8D4B300223765 /* IdentifierTable.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE3986EF0CB8D4B300223765 /* IdentifierTable.h */; };
                DE3461260AFE68BE00DBC861 /* MinimalAction.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = MinimalAction.cpp; path = Parse/MinimalAction.cpp; sourceTree = "<group>"; };
                DE34621C0AFEB19B00DBC861 /* StmtPrinter.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = StmtPrinter.cpp; path = AST/StmtPrinter.cpp; sourceTree = "<group>"; };
                DE3464210B03040900DBC861 /* Type.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Type.h; path = clang/AST/Type.h; sourceTree = "<group>"; };
+               DE38CD4E0D794CF900A273B6 /* CGObjCRuntime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CGObjCRuntime.h; path = CodeGen/CGObjCRuntime.h; sourceTree = "<group>"; };
+               DE38CD4F0D794D0100A273B6 /* CGObjCGNU.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CGObjCGNU.cpp; path = CodeGen/CGObjCGNU.cpp; sourceTree = "<group>"; };
                DE3985780CB8ADC800223765 /* ASTConsumers.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ASTConsumers.h; path = Driver/ASTConsumers.h; sourceTree = "<group>"; };
                DE39857A0CB8ADCB00223765 /* ASTConsumers.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ASTConsumers.cpp; path = Driver/ASTConsumers.cpp; sourceTree = "<group>"; };
                DE3986EF0CB8D4B300223765 /* IdentifierTable.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = IdentifierTable.h; sourceTree = "<group>"; };
                                1A376A2C0D4AED9B002A1C52 /* CGExprConstant.cpp */,
                                DE22526F0C7E82D000D370A5 /* CGExprScalar.cpp */,
                                1A7342470C7B57D500122F56 /* CGObjC.cpp */,
+                               DE38CD4E0D794CF900A273B6 /* CGObjCRuntime.h */,
+                               DE38CD4F0D794D0100A273B6 /* CGObjCGNU.cpp */,
                                DE4772F90C10EAE5002239E8 /* CGStmt.cpp */,
                                DE928B120C05659200231DA4 /* ModuleBuilder.cpp */,
                        );
                                DE47999C0D2EBE1A00706D2D /* SemaExprObjC.cpp in Sources */,
                                03F50AC60D416EAA00B9CF60 /* Targets.cpp in Sources */,
                                1A376A2D0D4AED9B002A1C52 /* CGExprConstant.cpp in Sources */,
+                               DE38CD500D794D0100A273B6 /* CGObjCGNU.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };