blob: 5bb8fac73b29dc448ebc372e7aaace05aefde380 [file] [log] [blame]
Chris Lattner391d77a2008-03-30 23:03:07 +00001//===------- CGObjCGNU.cpp - Emit LLVM Code from ASTs for a Module --------===//
Chris Lattner0f984262008-03-01 08:50:34 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This provides Objective-C code generation targetting the GNU runtime.
11//
12//===----------------------------------------------------------------------===//
13
14#include "CGObjCRuntime.h"
15#include "llvm/Module.h"
16#include "llvm/Support/Compiler.h"
Chris Lattner50b36742008-04-13 07:32:11 +000017#include "llvm/Support/IRBuilder.h"
Chris Lattner0f984262008-03-01 08:50:34 +000018#include "llvm/ADT/SmallVector.h"
19
Chris Lattner0f984262008-03-01 08:50:34 +000020namespace {
Chris Lattner391d77a2008-03-30 23:03:07 +000021class CGObjCGNU : public clang::CodeGen::CGObjCRuntime {
Chris Lattner0f984262008-03-01 08:50:34 +000022private:
23 llvm::Module &TheModule;
Chris Lattner391d77a2008-03-30 23:03:07 +000024 const llvm::Type *SelectorTy;
25 const llvm::Type *PtrToInt8Ty;
26 const llvm::Type *IMPTy;
27 const llvm::Type *IdTy;
28 const llvm::Type *IntTy;
29 const llvm::Type *PtrTy;
30 const llvm::Type *LongTy;
31 const llvm::Type *PtrToIntTy;
Chris Lattner0f984262008-03-01 08:50:34 +000032public:
Chris Lattner391d77a2008-03-30 23:03:07 +000033 CGObjCGNU(llvm::Module &Mp,
34 const llvm::Type *LLVMIntType,
35 const llvm::Type *LLVMLongType);
Chris Lattner50b36742008-04-13 07:32:11 +000036 virtual llvm::Value *generateMessageSend(llvm::IRBuilder &Builder,
Chris Lattner0f984262008-03-01 08:50:34 +000037 const llvm::Type *ReturnTy,
Chris Lattner391d77a2008-03-30 23:03:07 +000038 llvm::Value *Sender,
Chris Lattner0f984262008-03-01 08:50:34 +000039 llvm::Value *Receiver,
Chris Lattner391d77a2008-03-30 23:03:07 +000040 llvm::Value *Selector,
Chris Lattner0f984262008-03-01 08:50:34 +000041 llvm::Value** ArgV,
42 unsigned ArgC);
Chris Lattner50b36742008-04-13 07:32:11 +000043 llvm::Value *getSelector(llvm::IRBuilder &Builder,
Chris Lattner391d77a2008-03-30 23:03:07 +000044 llvm::Value *SelName,
45 llvm::Value *SelTypes);
46 virtual llvm::Function *MethodPreamble(const llvm::Type *ReturnTy,
47 const llvm::Type *SelfTy,
48 const llvm::Type **ArgTy,
49 unsigned ArgC,
50 bool isVarArg);
Chris Lattner0f984262008-03-01 08:50:34 +000051};
52} // end anonymous namespace
53
Chris Lattner391d77a2008-03-30 23:03:07 +000054CGObjCGNU::CGObjCGNU(llvm::Module &M,
55 const llvm::Type *LLVMIntType,
56 const llvm::Type *LLVMLongType) :
57 TheModule(M),
58 IntTy(LLVMIntType),
59 LongTy(LLVMLongType)
60{
61 // C string type. Used in lots of places.
62 PtrToInt8Ty =
63 llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
64 // Get the selector Type.
65 const llvm::Type *SelStructTy = llvm::StructType::get(
66 PtrToInt8Ty,
67 PtrToInt8Ty,
68 NULL);
69 SelectorTy = llvm::PointerType::getUnqual(SelStructTy);
70 PtrToIntTy = llvm::PointerType::getUnqual(IntTy);
71 PtrTy = PtrToInt8Ty;
72
73 // Object type
74 llvm::PATypeHolder OpaqueObjTy = llvm::OpaqueType::get();
75 llvm::Type *OpaqueIdTy = llvm::PointerType::getUnqual(OpaqueObjTy);
76 IdTy = llvm::StructType::get(OpaqueIdTy, NULL);
77 llvm::cast<llvm::OpaqueType>(OpaqueObjTy.get())->refineAbstractTypeTo(IdTy);
78 IdTy = llvm::cast<llvm::StructType>(OpaqueObjTy.get());
79 IdTy = llvm::PointerType::getUnqual(IdTy);
80
81 // IMP type
82 std::vector<const llvm::Type*> IMPArgs;
83 IMPArgs.push_back(IdTy);
84 IMPArgs.push_back(SelectorTy);
85 IMPTy = llvm::FunctionType::get(IdTy, IMPArgs, true);
86
87}
88
89/// Looks up the selector for the specified name / type pair.
90// FIXME: Selectors should be statically cached, not looked up on every call.
Chris Lattner50b36742008-04-13 07:32:11 +000091llvm::Value *CGObjCGNU::getSelector(llvm::IRBuilder &Builder,
Chris Lattner391d77a2008-03-30 23:03:07 +000092 llvm::Value *SelName,
93 llvm::Value *SelTypes)
94{
95 // Look up the selector.
96 llvm::Value *cmd;
97 if(SelTypes == 0) {
98 llvm::Constant *SelFunction = TheModule.getOrInsertFunction("sel_get_uid",
99 SelectorTy,
100 PtrToInt8Ty,
101 NULL);
102 cmd = Builder.CreateCall(SelFunction, SelName);
103 }
104 else {
105 llvm::Constant *SelFunction =
106 TheModule.getOrInsertFunction("sel_get_typed_uid",
107 SelectorTy,
108 PtrToInt8Ty,
109 PtrToInt8Ty,
110 NULL);
111 llvm::Value *Args[] = { SelName, SelTypes };
112 cmd = Builder.CreateCall(SelFunction, Args, Args+2);
113 }
114 return cmd;
115}
116
117
118/// Generate code for a message send expression on the GNU runtime.
119// FIXME: Much of this code will need factoring out later.
120// TODO: This should take a sender argument (pointer to self in the calling
121// context)
Chris Lattner50b36742008-04-13 07:32:11 +0000122llvm::Value *CGObjCGNU::generateMessageSend(llvm::IRBuilder &Builder,
Chris Lattner0f984262008-03-01 08:50:34 +0000123 const llvm::Type *ReturnTy,
Chris Lattner391d77a2008-03-30 23:03:07 +0000124 llvm::Value *Sender,
Chris Lattner0f984262008-03-01 08:50:34 +0000125 llvm::Value *Receiver,
Chris Lattner391d77a2008-03-30 23:03:07 +0000126 llvm::Value *Selector,
Chris Lattner0f984262008-03-01 08:50:34 +0000127 llvm::Value** ArgV,
128 unsigned ArgC) {
Chris Lattner391d77a2008-03-30 23:03:07 +0000129 llvm::Value *cmd = getSelector(Builder, Selector, 0);
Chris Lattner0f984262008-03-01 08:50:34 +0000130
131 // Look up the method implementation.
132 std::vector<const llvm::Type*> impArgTypes;
133 impArgTypes.push_back(Receiver->getType());
Chris Lattner391d77a2008-03-30 23:03:07 +0000134 impArgTypes.push_back(SelectorTy);
Chris Lattner0f984262008-03-01 08:50:34 +0000135
136 // Avoid an explicit cast on the IMP by getting a version that has the right
137 // return type.
138 llvm::FunctionType *impType = llvm::FunctionType::get(ReturnTy, impArgTypes,
139 true);
140
141 llvm::Constant *lookupFunction =
142 TheModule.getOrInsertFunction("objc_msg_lookup",
Chris Lattner391d77a2008-03-30 23:03:07 +0000143 llvm::PointerType::getUnqual(impType),
144 Receiver->getType(), SelectorTy, NULL);
Chris Lattner0f984262008-03-01 08:50:34 +0000145 llvm::SmallVector<llvm::Value*, 16> lookupArgs;
146 lookupArgs.push_back(Receiver);
147 lookupArgs.push_back(cmd);
148 llvm::Value *imp = Builder.CreateCall(lookupFunction,
149 lookupArgs.begin(), lookupArgs.end());
150
151 // Call the method.
152 lookupArgs.insert(lookupArgs.end(), ArgV, ArgV+ArgC);
153 return Builder.CreateCall(imp, lookupArgs.begin(), lookupArgs.end());
154}
155
Chris Lattner391d77a2008-03-30 23:03:07 +0000156llvm::Function *CGObjCGNU::MethodPreamble(
157 const llvm::Type *ReturnTy,
158 const llvm::Type *SelfTy,
159 const llvm::Type **ArgTy,
160 unsigned ArgC,
161 bool isVarArg) {
162 std::vector<const llvm::Type*> Args;
163 Args.push_back(SelfTy);
164 Args.push_back(SelectorTy);
165 Args.insert(Args.end(), ArgTy, ArgTy+ArgC);
166
167 llvm::FunctionType *MethodTy = llvm::FunctionType::get(ReturnTy,
168 Args,
169 isVarArg);
Gabor Greif984d0b42008-04-06 20:42:52 +0000170 llvm::Function *Method = llvm::Function::Create(MethodTy,
Chris Lattner391d77a2008-03-30 23:03:07 +0000171 llvm::GlobalValue::InternalLinkage,
172 ".objc.method",
173 &TheModule);
174 // Set the names of the hidden arguments
175 llvm::Function::arg_iterator AI = Method->arg_begin();
176 AI->setName("self");
177 ++AI;
178 AI->setName("_cmd");
179 return Method;
180}
181
182clang::CodeGen::CGObjCRuntime *clang::CodeGen::CreateObjCRuntime(
183 llvm::Module &M,
184 const llvm::Type *LLVMIntType,
185 const llvm::Type *LLVMLongType) {
186 return new CGObjCGNU(M, LLVMIntType, LLVMLongType);
Chris Lattner0f984262008-03-01 08:50:34 +0000187}