blob: 9d97d475caa879bc858ef5129f47236e1fffb502 [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"
17#include "llvm/Support/LLVMBuilder.h"
18#include "llvm/ADT/SmallVector.h"
19
Chris Lattner0f984262008-03-01 08:50:34 +000020
Chris Lattner391d77a2008-03-30 23:03:07 +000021clang::CodeGen::CGObjCRuntime::~CGObjCRuntime() {}
Chris Lattner0f984262008-03-01 08:50:34 +000022
23namespace {
Chris Lattner391d77a2008-03-30 23:03:07 +000024class CGObjCGNU : public clang::CodeGen::CGObjCRuntime {
Chris Lattner0f984262008-03-01 08:50:34 +000025private:
26 llvm::Module &TheModule;
Chris Lattner391d77a2008-03-30 23:03:07 +000027 const llvm::Type *SelectorTy;
28 const llvm::Type *PtrToInt8Ty;
29 const llvm::Type *IMPTy;
30 const llvm::Type *IdTy;
31 const llvm::Type *IntTy;
32 const llvm::Type *PtrTy;
33 const llvm::Type *LongTy;
34 const llvm::Type *PtrToIntTy;
Chris Lattner0f984262008-03-01 08:50:34 +000035public:
Chris Lattner391d77a2008-03-30 23:03:07 +000036 CGObjCGNU(llvm::Module &Mp,
37 const llvm::Type *LLVMIntType,
38 const llvm::Type *LLVMLongType);
Chris Lattner0f984262008-03-01 08:50:34 +000039 virtual llvm::Value *generateMessageSend(llvm::LLVMFoldingBuilder &Builder,
40 const llvm::Type *ReturnTy,
Chris Lattner391d77a2008-03-30 23:03:07 +000041 llvm::Value *Sender,
Chris Lattner0f984262008-03-01 08:50:34 +000042 llvm::Value *Receiver,
Chris Lattner391d77a2008-03-30 23:03:07 +000043 llvm::Value *Selector,
Chris Lattner0f984262008-03-01 08:50:34 +000044 llvm::Value** ArgV,
45 unsigned ArgC);
Chris Lattner391d77a2008-03-30 23:03:07 +000046 llvm::Value *getSelector(llvm::LLVMFoldingBuilder &Builder,
47 llvm::Value *SelName,
48 llvm::Value *SelTypes);
49 virtual llvm::Function *MethodPreamble(const llvm::Type *ReturnTy,
50 const llvm::Type *SelfTy,
51 const llvm::Type **ArgTy,
52 unsigned ArgC,
53 bool isVarArg);
Chris Lattner0f984262008-03-01 08:50:34 +000054};
55} // end anonymous namespace
56
Chris Lattner391d77a2008-03-30 23:03:07 +000057CGObjCGNU::CGObjCGNU(llvm::Module &M,
58 const llvm::Type *LLVMIntType,
59 const llvm::Type *LLVMLongType) :
60 TheModule(M),
61 IntTy(LLVMIntType),
62 LongTy(LLVMLongType)
63{
64 // C string type. Used in lots of places.
65 PtrToInt8Ty =
66 llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
67 // Get the selector Type.
68 const llvm::Type *SelStructTy = llvm::StructType::get(
69 PtrToInt8Ty,
70 PtrToInt8Ty,
71 NULL);
72 SelectorTy = llvm::PointerType::getUnqual(SelStructTy);
73 PtrToIntTy = llvm::PointerType::getUnqual(IntTy);
74 PtrTy = PtrToInt8Ty;
75
76 // Object type
77 llvm::PATypeHolder OpaqueObjTy = llvm::OpaqueType::get();
78 llvm::Type *OpaqueIdTy = llvm::PointerType::getUnqual(OpaqueObjTy);
79 IdTy = llvm::StructType::get(OpaqueIdTy, NULL);
80 llvm::cast<llvm::OpaqueType>(OpaqueObjTy.get())->refineAbstractTypeTo(IdTy);
81 IdTy = llvm::cast<llvm::StructType>(OpaqueObjTy.get());
82 IdTy = llvm::PointerType::getUnqual(IdTy);
83
84 // IMP type
85 std::vector<const llvm::Type*> IMPArgs;
86 IMPArgs.push_back(IdTy);
87 IMPArgs.push_back(SelectorTy);
88 IMPTy = llvm::FunctionType::get(IdTy, IMPArgs, true);
89
90}
91
92/// Looks up the selector for the specified name / type pair.
93// FIXME: Selectors should be statically cached, not looked up on every call.
94llvm::Value *CGObjCGNU::getSelector(llvm::LLVMFoldingBuilder &Builder,
95 llvm::Value *SelName,
96 llvm::Value *SelTypes)
97{
98 // Look up the selector.
99 llvm::Value *cmd;
100 if(SelTypes == 0) {
101 llvm::Constant *SelFunction = TheModule.getOrInsertFunction("sel_get_uid",
102 SelectorTy,
103 PtrToInt8Ty,
104 NULL);
105 cmd = Builder.CreateCall(SelFunction, SelName);
106 }
107 else {
108 llvm::Constant *SelFunction =
109 TheModule.getOrInsertFunction("sel_get_typed_uid",
110 SelectorTy,
111 PtrToInt8Ty,
112 PtrToInt8Ty,
113 NULL);
114 llvm::Value *Args[] = { SelName, SelTypes };
115 cmd = Builder.CreateCall(SelFunction, Args, Args+2);
116 }
117 return cmd;
118}
119
120
121/// Generate code for a message send expression on the GNU runtime.
122// FIXME: Much of this code will need factoring out later.
123// TODO: This should take a sender argument (pointer to self in the calling
124// context)
Chris Lattner0f984262008-03-01 08:50:34 +0000125llvm::Value *CGObjCGNU::generateMessageSend(llvm::LLVMFoldingBuilder &Builder,
126 const llvm::Type *ReturnTy,
Chris Lattner391d77a2008-03-30 23:03:07 +0000127 llvm::Value *Sender,
Chris Lattner0f984262008-03-01 08:50:34 +0000128 llvm::Value *Receiver,
Chris Lattner391d77a2008-03-30 23:03:07 +0000129 llvm::Value *Selector,
Chris Lattner0f984262008-03-01 08:50:34 +0000130 llvm::Value** ArgV,
131 unsigned ArgC) {
Chris Lattner391d77a2008-03-30 23:03:07 +0000132 llvm::Value *cmd = getSelector(Builder, Selector, 0);
Chris Lattner0f984262008-03-01 08:50:34 +0000133
134 // Look up the method implementation.
135 std::vector<const llvm::Type*> impArgTypes;
136 impArgTypes.push_back(Receiver->getType());
Chris Lattner391d77a2008-03-30 23:03:07 +0000137 impArgTypes.push_back(SelectorTy);
Chris Lattner0f984262008-03-01 08:50:34 +0000138
139 // Avoid an explicit cast on the IMP by getting a version that has the right
140 // return type.
141 llvm::FunctionType *impType = llvm::FunctionType::get(ReturnTy, impArgTypes,
142 true);
143
144 llvm::Constant *lookupFunction =
145 TheModule.getOrInsertFunction("objc_msg_lookup",
Chris Lattner391d77a2008-03-30 23:03:07 +0000146 llvm::PointerType::getUnqual(impType),
147 Receiver->getType(), SelectorTy, NULL);
Chris Lattner0f984262008-03-01 08:50:34 +0000148 llvm::SmallVector<llvm::Value*, 16> lookupArgs;
149 lookupArgs.push_back(Receiver);
150 lookupArgs.push_back(cmd);
151 llvm::Value *imp = Builder.CreateCall(lookupFunction,
152 lookupArgs.begin(), lookupArgs.end());
153
154 // Call the method.
155 lookupArgs.insert(lookupArgs.end(), ArgV, ArgV+ArgC);
156 return Builder.CreateCall(imp, lookupArgs.begin(), lookupArgs.end());
157}
158
Chris Lattner391d77a2008-03-30 23:03:07 +0000159llvm::Function *CGObjCGNU::MethodPreamble(
160 const llvm::Type *ReturnTy,
161 const llvm::Type *SelfTy,
162 const llvm::Type **ArgTy,
163 unsigned ArgC,
164 bool isVarArg) {
165 std::vector<const llvm::Type*> Args;
166 Args.push_back(SelfTy);
167 Args.push_back(SelectorTy);
168 Args.insert(Args.end(), ArgTy, ArgTy+ArgC);
169
170 llvm::FunctionType *MethodTy = llvm::FunctionType::get(ReturnTy,
171 Args,
172 isVarArg);
Gabor Greif984d0b42008-04-06 20:42:52 +0000173 llvm::Function *Method = llvm::Function::Create(MethodTy,
Chris Lattner391d77a2008-03-30 23:03:07 +0000174 llvm::GlobalValue::InternalLinkage,
175 ".objc.method",
176 &TheModule);
177 // Set the names of the hidden arguments
178 llvm::Function::arg_iterator AI = Method->arg_begin();
179 AI->setName("self");
180 ++AI;
181 AI->setName("_cmd");
182 return Method;
183}
184
185clang::CodeGen::CGObjCRuntime *clang::CodeGen::CreateObjCRuntime(
186 llvm::Module &M,
187 const llvm::Type *LLVMIntType,
188 const llvm::Type *LLVMLongType) {
189 return new CGObjCGNU(M, LLVMIntType, LLVMLongType);
Chris Lattner0f984262008-03-01 08:50:34 +0000190}