aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGObjCGNU.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/CGObjCGNU.cpp')
-rw-r--r--lib/CodeGen/CGObjCGNU.cpp165
1 files changed, 129 insertions, 36 deletions
diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp
index 1cc5cffb82..dd0eaa3b7c 100644
--- a/lib/CodeGen/CGObjCGNU.cpp
+++ b/lib/CodeGen/CGObjCGNU.cpp
@@ -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::Value *CGObjCGNU::generateMessageSend(llvm::LLVMFoldingBuilder &Builder,
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 @@ llvm::Value *CGObjCGNU::generateMessageSend(llvm::LLVMFoldingBuilder &Builder,
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);
}