Mercurial > projects > ldc
annotate gen/functions.cpp @ 117:56a21f3e5d3e trunk
[svn r121] Finished ModuleInfo implementation.
Static ctors/dtors now work according to spec.
Changed class vtable types slightly in some cases. Overridden functions now always take the the type of the first class declaring the method as this parameter. This helps when using headers (w. implementation somewhere else)
author | lindquist |
---|---|
date | Mon, 26 Nov 2007 04:49:23 +0100 |
parents | fd7ad91fd713 |
children | 79c9ac745fbc |
rev | line source |
---|---|
100 | 1 #include "gen/llvm.h" |
2 | |
3 #include "mtype.h" | |
4 #include "aggregate.h" | |
5 #include "init.h" | |
6 #include "declaration.h" | |
7 #include "template.h" | |
8 #include "module.h" | |
9 #include "statement.h" | |
10 | |
11 #include "gen/irstate.h" | |
12 #include "gen/tollvm.h" | |
13 #include "gen/runtime.h" | |
14 #include "gen/arrays.h" | |
15 #include "gen/logger.h" | |
16 #include "gen/functions.h" | |
17 #include "gen/todebug.h" | |
18 #include "gen/classes.h" | |
19 | |
20 const llvm::FunctionType* DtoFunctionType(Type* type, const llvm::Type* thistype, bool ismain) | |
21 { | |
22 TypeFunction* f = (TypeFunction*)type; | |
23 assert(f != 0); | |
24 | |
25 if (type->llvmType != NULL) { | |
26 return llvm::cast<llvm::FunctionType>(type->llvmType->get()); | |
27 } | |
28 | |
29 bool typesafeVararg = false; | |
30 if (f->linkage == LINKd && f->varargs == 1) { | |
31 typesafeVararg = true; | |
32 } | |
33 | |
34 // return value type | |
35 const llvm::Type* rettype; | |
36 const llvm::Type* actualRettype; | |
37 Type* rt = f->next; | |
38 bool retinptr = false; | |
39 bool usesthis = false; | |
40 | |
41 if (ismain) { | |
42 rettype = llvm::Type::Int32Ty; | |
43 actualRettype = rettype; | |
44 } | |
45 else { | |
46 assert(rt); | |
109
5ab8e92611f9
[svn r113] Added initial support for associative arrays (AAs).
lindquist
parents:
108
diff
changeset
|
47 Type* rtfin = DtoDType(rt); |
100 | 48 if (DtoIsPassedByRef(rt)) { |
49 rettype = llvm::PointerType::get(DtoType(rt)); | |
50 actualRettype = llvm::Type::VoidTy; | |
51 f->llvmRetInPtr = retinptr = true; | |
52 } | |
53 else { | |
54 rettype = DtoType(rt); | |
55 actualRettype = rettype; | |
56 } | |
57 } | |
58 | |
59 // parameter types | |
60 std::vector<const llvm::Type*> paramvec; | |
61 | |
62 if (retinptr) { | |
63 Logger::cout() << "returning through pointer parameter: " << *rettype << '\n'; | |
64 paramvec.push_back(rettype); | |
65 } | |
66 | |
67 if (thistype) { | |
68 paramvec.push_back(thistype); | |
69 usesthis = true; | |
70 } | |
71 | |
72 if (typesafeVararg) { | |
73 ClassDeclaration* ti = Type::typeinfo; | |
74 ti->toObjFile(); | |
102
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
75 DtoForceConstInitDsymbol(ti); |
100 | 76 assert(ti->llvmInitZ); |
77 std::vector<const llvm::Type*> types; | |
78 types.push_back(DtoSize_t()); | |
79 types.push_back(llvm::PointerType::get(llvm::PointerType::get(ti->llvmInitZ->getType()))); | |
80 const llvm::Type* t1 = llvm::StructType::get(types); | |
81 paramvec.push_back(llvm::PointerType::get(t1)); | |
82 paramvec.push_back(llvm::PointerType::get(llvm::Type::Int8Ty)); | |
83 } | |
84 | |
85 size_t n = Argument::dim(f->parameters); | |
86 | |
87 for (int i=0; i < n; ++i) { | |
88 Argument* arg = Argument::getNth(f->parameters, i); | |
89 // ensure scalar | |
90 Type* argT = DtoDType(arg->type); | |
91 assert(argT); | |
92 | |
93 if ((arg->storageClass & STCref) || (arg->storageClass & STCout)) { | |
94 //assert(arg->vardecl); | |
95 //arg->vardecl->refparam = true; | |
96 } | |
97 else | |
98 arg->llvmCopy = true; | |
99 | |
100 const llvm::Type* at = DtoType(argT); | |
101 if (isaStruct(at)) { | |
102 Logger::println("struct param"); | |
103 paramvec.push_back(llvm::PointerType::get(at)); | |
104 } | |
105 else if (isaArray(at)) { | |
106 Logger::println("sarray param"); | |
107 assert(argT->ty == Tsarray); | |
108 //paramvec.push_back(llvm::PointerType::get(at->getContainedType(0))); | |
109 paramvec.push_back(llvm::PointerType::get(at)); | |
110 } | |
111 else if (llvm::isa<llvm::OpaqueType>(at)) { | |
112 Logger::println("opaque param"); | |
113 assert(argT->ty == Tstruct || argT->ty == Tclass); | |
114 paramvec.push_back(llvm::PointerType::get(at)); | |
115 } | |
116 else { | |
117 if (!arg->llvmCopy) { | |
118 Logger::println("ref param"); | |
119 at = llvm::PointerType::get(at); | |
120 } | |
121 else { | |
122 Logger::println("in param"); | |
123 } | |
124 paramvec.push_back(at); | |
125 } | |
126 } | |
127 | |
128 // construct function type | |
129 bool isvararg = !typesafeVararg && f->varargs; | |
130 llvm::FunctionType* functype = llvm::FunctionType::get(actualRettype, paramvec, isvararg); | |
131 | |
132 f->llvmRetInPtr = retinptr; | |
133 f->llvmUsesThis = usesthis; | |
134 | |
102
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
135 //if (!f->llvmType) |
100 | 136 f->llvmType = new llvm::PATypeHolder(functype); |
102
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
137 //else |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
138 //assert(functype == f->llvmType->get()); |
100 | 139 |
140 return functype; | |
141 } | |
142 | |
143 ////////////////////////////////////////////////////////////////////////////////////////// | |
144 | |
145 static const llvm::FunctionType* DtoVaFunctionType(FuncDeclaration* fdecl) | |
146 { | |
102
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
147 // type has already been resolved |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
148 if (fdecl->type->llvmType != 0) { |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
149 return llvm::cast<llvm::FunctionType>(fdecl->type->llvmType->get()); |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
150 } |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
151 |
100 | 152 TypeFunction* f = (TypeFunction*)fdecl->type; |
153 assert(f != 0); | |
154 | |
155 const llvm::PointerType* i8pty = llvm::PointerType::get(llvm::Type::Int8Ty); | |
156 std::vector<const llvm::Type*> args; | |
157 | |
158 if (fdecl->llvmInternal == LLVMva_start) { | |
159 args.push_back(i8pty); | |
160 } | |
161 else if (fdecl->llvmInternal == LLVMva_intrinsic) { | |
162 size_t n = Argument::dim(f->parameters); | |
163 for (size_t i=0; i<n; ++i) { | |
164 args.push_back(i8pty); | |
165 } | |
166 } | |
167 else | |
168 assert(0); | |
169 | |
170 const llvm::FunctionType* fty = llvm::FunctionType::get(llvm::Type::VoidTy, args, false); | |
171 | |
102
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
172 f->llvmType = new llvm::PATypeHolder(fty); |
100 | 173 |
174 return fty; | |
175 } | |
176 | |
177 ////////////////////////////////////////////////////////////////////////////////////////// | |
178 | |
179 const llvm::FunctionType* DtoFunctionType(FuncDeclaration* fdecl) | |
180 { | |
181 if ((fdecl->llvmInternal == LLVMva_start) || (fdecl->llvmInternal == LLVMva_intrinsic)) { | |
182 return DtoVaFunctionType(fdecl); | |
183 } | |
184 | |
185 // type has already been resolved | |
186 if (fdecl->type->llvmType != 0) { | |
187 return llvm::cast<llvm::FunctionType>(fdecl->type->llvmType->get()); | |
188 } | |
189 | |
190 const llvm::Type* thisty = NULL; | |
191 if (fdecl->needThis()) { | |
192 if (AggregateDeclaration* ad = fdecl->isMember()) { | |
193 Logger::print("isMember = this is: %s\n", ad->type->toChars()); | |
194 thisty = DtoType(ad->type); | |
113
27b9f749d9fe
[svn r117] Initial working implementation of interfaces.
lindquist
parents:
109
diff
changeset
|
195 //Logger::cout() << "this llvm type: " << *thisty << '\n'; |
102
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
196 if (isaStruct(thisty) || (!gIR->structs.empty() && thisty == gIR->topstruct()->recty.get())) |
100 | 197 thisty = llvm::PointerType::get(thisty); |
198 } | |
199 else | |
200 assert(0); | |
201 } | |
202 else if (fdecl->isNested()) { | |
203 thisty = llvm::PointerType::get(llvm::Type::Int8Ty); | |
204 } | |
205 | |
206 const llvm::FunctionType* functype = DtoFunctionType(fdecl->type, thisty, fdecl->isMain()); | |
207 | |
208 return functype; | |
209 } | |
210 | |
211 ////////////////////////////////////////////////////////////////////////////////////////// | |
212 | |
213 static llvm::Function* DtoDeclareVaFunction(FuncDeclaration* fdecl) | |
214 { | |
215 TypeFunction* f = (TypeFunction*)DtoDType(fdecl->type); | |
216 const llvm::FunctionType* fty = DtoVaFunctionType(fdecl); | |
217 llvm::Constant* fn = 0; | |
218 | |
219 if (fdecl->llvmInternal == LLVMva_start) { | |
220 fn = gIR->module->getOrInsertFunction("llvm.va_start", fty); | |
221 assert(fn); | |
222 } | |
223 else if (fdecl->llvmInternal == LLVMva_intrinsic) { | |
224 fn = gIR->module->getOrInsertFunction(fdecl->llvmInternal1, fty); | |
225 assert(fn); | |
226 } | |
227 else | |
228 assert(0); | |
229 | |
230 llvm::Function* func = llvm::dyn_cast<llvm::Function>(fn); | |
231 assert(func); | |
232 assert(func->isIntrinsic()); | |
233 fdecl->llvmValue = func; | |
234 return func; | |
235 } | |
236 | |
237 ////////////////////////////////////////////////////////////////////////////////////////// | |
238 | |
102
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
239 void DtoResolveFunction(FuncDeclaration* fdecl) |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
240 { |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
241 if (fdecl->llvmResolved) return; |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
242 fdecl->llvmResolved = true; |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
243 |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
244 Logger::println("DtoResolveFunction(%s)", fdecl->toPrettyChars()); |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
245 LOG_SCOPE; |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
246 |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
247 if (fdecl->llvmRunTimeHack) { |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
248 gIR->declareList.push_back(fdecl); |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
249 return; |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
250 } |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
251 |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
252 if (fdecl->isUnitTestDeclaration()) { |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
253 Logger::attention("ignoring unittest declaration: %s", fdecl->toChars()); |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
254 return; |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
255 } |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
256 |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
257 if (fdecl->parent) |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
258 if (TemplateInstance* tinst = fdecl->parent->isTemplateInstance()) |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
259 { |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
260 TemplateDeclaration* tempdecl = tinst->tempdecl; |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
261 if (tempdecl->llvmInternal == LLVMva_arg) |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
262 { |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
263 Logger::println("magic va_arg found"); |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
264 fdecl->llvmInternal = LLVMva_arg; |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
265 fdecl->llvmDeclared = true; |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
266 fdecl->llvmInitialized = true; |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
267 fdecl->llvmDefined = true; |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
268 return; // this gets mapped to an instruction so a declaration makes no sence |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
269 } |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
270 else if (tempdecl->llvmInternal == LLVMva_start) |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
271 { |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
272 Logger::println("magic va_start found"); |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
273 fdecl->llvmInternal = LLVMva_start; |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
274 } |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
275 } |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
276 |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
277 DtoFunctionType(fdecl); |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
278 |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
279 // queue declaration |
113
27b9f749d9fe
[svn r117] Initial working implementation of interfaces.
lindquist
parents:
109
diff
changeset
|
280 if (!fdecl->isAbstract()) |
27b9f749d9fe
[svn r117] Initial working implementation of interfaces.
lindquist
parents:
109
diff
changeset
|
281 gIR->declareList.push_back(fdecl); |
102
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
282 } |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
283 |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
284 ////////////////////////////////////////////////////////////////////////////////////////// |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
285 |
100 | 286 void DtoDeclareFunction(FuncDeclaration* fdecl) |
287 { | |
102
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
288 if (fdecl->llvmDeclared) return; |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
289 fdecl->llvmDeclared = true; |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
290 |
100 | 291 Logger::println("DtoDeclareFunction(%s)", fdecl->toPrettyChars()); |
292 LOG_SCOPE; | |
293 | |
113
27b9f749d9fe
[svn r117] Initial working implementation of interfaces.
lindquist
parents:
109
diff
changeset
|
294 assert(!fdecl->isAbstract()); |
27b9f749d9fe
[svn r117] Initial working implementation of interfaces.
lindquist
parents:
109
diff
changeset
|
295 |
100 | 296 if (fdecl->llvmRunTimeHack) { |
297 Logger::println("runtime hack func chars: %s", fdecl->toChars()); | |
298 if (!fdecl->llvmValue) | |
299 fdecl->llvmValue = LLVM_D_GetRuntimeFunction(gIR->module, fdecl->toChars()); | |
300 return; | |
301 } | |
302 | |
303 bool declareOnly = false; | |
102
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
304 bool templInst = fdecl->parent && DtoIsTemplateInstance(fdecl->parent); |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
305 if (!templInst && fdecl->getModule() != gIR->dmodule) |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
306 declareOnly = true; |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
307 else if (fdecl->llvmInternal == LLVMva_start) |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
308 declareOnly = true; |
100 | 309 |
310 if (!fdecl->llvmIRFunc) { | |
311 fdecl->llvmIRFunc = new IRFunction(fdecl); | |
312 } | |
313 | |
314 // mangled name | |
315 char* mangled_name; | |
316 if (fdecl->llvmInternal == LLVMintrinsic) | |
317 mangled_name = fdecl->llvmInternal1; | |
318 else | |
319 mangled_name = fdecl->mangle(); | |
320 | |
321 // unit test special handling | |
322 if (fdecl->isUnitTestDeclaration()) | |
323 { | |
324 assert(0 && "no unittests yet"); | |
325 /*const llvm::FunctionType* fnty = llvm::FunctionType::get(llvm::Type::VoidTy, std::vector<const llvm::Type*>(), false); | |
326 // make the function | |
327 llvm::Function* func = gIR->module->getFunction(mangled_name); | |
328 if (func == 0) | |
329 func = new llvm::Function(fnty,llvm::GlobalValue::InternalLinkage,mangled_name,gIR->module); | |
330 func->setCallingConv(llvm::CallingConv::Fast); | |
331 fdecl->llvmValue = func; | |
332 return func; | |
333 */ | |
334 } | |
335 | |
336 if (fdecl->llvmInternal == LLVMintrinsic && fdecl->fbody) { | |
337 error("intrinsics cannot have function bodies"); | |
338 fatal(); | |
339 } | |
340 | |
341 llvm::Function* vafunc = 0; | |
342 if ((fdecl->llvmInternal == LLVMva_start) || (fdecl->llvmInternal == LLVMva_intrinsic)) { | |
343 vafunc = DtoDeclareVaFunction(fdecl); | |
344 } | |
345 | |
346 Type* t = DtoDType(fdecl->type); | |
347 TypeFunction* f = (TypeFunction*)t; | |
348 | |
349 // construct function | |
350 const llvm::FunctionType* functype = DtoFunctionType(fdecl); | |
351 llvm::Function* func = vafunc ? vafunc : gIR->module->getFunction(mangled_name); | |
352 if (!func) | |
353 func = new llvm::Function(functype, DtoLinkage(fdecl->protection, fdecl->storage_class), mangled_name, gIR->module); | |
354 else | |
355 assert(func->getFunctionType() == functype); | |
356 | |
357 // add func to IRFunc | |
358 fdecl->llvmIRFunc->func = func; | |
359 | |
360 // calling convention | |
361 if (!vafunc && fdecl->llvmInternal != LLVMintrinsic) | |
362 func->setCallingConv(DtoCallingConv(f->linkage)); | |
363 | |
364 // template instances should have weak linkage | |
365 if (!vafunc && fdecl->llvmInternal != LLVMintrinsic && fdecl->parent && DtoIsTemplateInstance(fdecl->parent)) | |
366 func->setLinkage(llvm::GlobalValue::WeakLinkage); | |
367 | |
368 fdecl->llvmValue = func; | |
369 assert(llvm::isa<llvm::FunctionType>(f->llvmType->get())); | |
370 | |
116
fd7ad91fd713
[svn r120] ModuleInfo implementation is now almost complete.
lindquist
parents:
113
diff
changeset
|
371 // main |
100 | 372 if (fdecl->isMain()) { |
373 gIR->mainFunc = func; | |
374 } | |
375 | |
116
fd7ad91fd713
[svn r120] ModuleInfo implementation is now almost complete.
lindquist
parents:
113
diff
changeset
|
376 // static ctor |
fd7ad91fd713
[svn r120] ModuleInfo implementation is now almost complete.
lindquist
parents:
113
diff
changeset
|
377 if (fdecl->isStaticCtorDeclaration()) { |
fd7ad91fd713
[svn r120] ModuleInfo implementation is now almost complete.
lindquist
parents:
113
diff
changeset
|
378 gIR->ctors.push_back(fdecl); |
fd7ad91fd713
[svn r120] ModuleInfo implementation is now almost complete.
lindquist
parents:
113
diff
changeset
|
379 } |
fd7ad91fd713
[svn r120] ModuleInfo implementation is now almost complete.
lindquist
parents:
113
diff
changeset
|
380 // static dtor |
fd7ad91fd713
[svn r120] ModuleInfo implementation is now almost complete.
lindquist
parents:
113
diff
changeset
|
381 else if (fdecl->isStaticDtorDeclaration()) { |
fd7ad91fd713
[svn r120] ModuleInfo implementation is now almost complete.
lindquist
parents:
113
diff
changeset
|
382 gIR->dtors.push_back(fdecl); |
fd7ad91fd713
[svn r120] ModuleInfo implementation is now almost complete.
lindquist
parents:
113
diff
changeset
|
383 } |
fd7ad91fd713
[svn r120] ModuleInfo implementation is now almost complete.
lindquist
parents:
113
diff
changeset
|
384 |
100 | 385 // name parameters |
386 llvm::Function::arg_iterator iarg = func->arg_begin(); | |
387 int k = 0; | |
388 if (f->llvmRetInPtr) { | |
389 iarg->setName("retval"); | |
390 f->llvmRetArg = iarg; | |
391 ++iarg; | |
392 } | |
393 if (f->llvmUsesThis) { | |
394 iarg->setName("this"); | |
108
288fe1029e1f
[svn r112] Fixed 'case 1,2,3:' style case statements.
lindquist
parents:
102
diff
changeset
|
395 fdecl->llvmThisVar = iarg; |
288fe1029e1f
[svn r112] Fixed 'case 1,2,3:' style case statements.
lindquist
parents:
102
diff
changeset
|
396 assert(fdecl->llvmThisVar); |
100 | 397 ++iarg; |
398 } | |
399 int varargs = -1; | |
400 if (f->linkage == LINKd && f->varargs == 1) | |
401 varargs = 0; | |
402 for (; iarg != func->arg_end(); ++iarg) | |
403 { | |
404 Argument* arg = Argument::getNth(f->parameters, k++); | |
405 //arg->llvmValue = iarg; | |
406 //Logger::println("identifier: '%s' %p\n", arg->ident->toChars(), arg->ident); | |
407 if (arg && arg->ident != 0) { | |
408 if (arg->vardecl) { | |
409 arg->vardecl->llvmValue = iarg; | |
410 } | |
411 iarg->setName(arg->ident->toChars()); | |
412 } | |
413 else if (!arg && varargs >= 0) { | |
414 if (varargs == 0) { | |
415 iarg->setName("_arguments"); | |
416 fdecl->llvmArguments = iarg; | |
417 } | |
418 else if (varargs == 1) { | |
419 iarg->setName("_argptr"); | |
420 fdecl->llvmArgPtr = iarg; | |
421 } | |
422 else | |
423 assert(0); | |
424 varargs++; | |
425 } | |
426 else { | |
427 iarg->setName("unnamed"); | |
428 } | |
429 } | |
430 | |
431 if (!declareOnly) | |
102
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
432 gIR->defineList.push_back(fdecl); |
100 | 433 |
434 Logger::cout() << "func decl: " << *func << '\n'; | |
435 } | |
436 | |
437 ////////////////////////////////////////////////////////////////////////////////////////// | |
438 | |
439 // TODO split this monster up | |
440 void DtoDefineFunc(FuncDeclaration* fd) | |
441 { | |
102
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
442 if (fd->llvmDefined) return; |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
443 fd->llvmDefined = true; |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
444 |
108
288fe1029e1f
[svn r112] Fixed 'case 1,2,3:' style case statements.
lindquist
parents:
102
diff
changeset
|
445 assert(fd->llvmDeclared); |
288fe1029e1f
[svn r112] Fixed 'case 1,2,3:' style case statements.
lindquist
parents:
102
diff
changeset
|
446 |
102
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
447 Logger::println("DtoDefineFunc(%s)", fd->toPrettyChars()); |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
448 LOG_SCOPE; |
027b8d8b71ec
[svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up.
lindquist
parents:
100
diff
changeset
|
449 |
100 | 450 // debug info |
451 if (global.params.symdebug) { | |
452 Module* mo = fd->getModule(); | |
453 if (!mo->llvmCompileUnit) { | |
454 mo->llvmCompileUnit = DtoDwarfCompileUnit(mo,false); | |
455 } | |
456 fd->llvmDwarfSubProgram = DtoDwarfSubProgram(fd, mo->llvmCompileUnit); | |
457 } | |
458 | |
459 Type* t = DtoDType(fd->type); | |
460 TypeFunction* f = (TypeFunction*)t; | |
461 | |
462 assert(f->llvmType); | |
463 llvm::Function* func = fd->llvmIRFunc->func; | |
464 const llvm::FunctionType* functype = func->getFunctionType(); | |
465 | |
466 // only members of the current module or template instances maybe be defined | |
467 if (fd->getModule() == gIR->dmodule || DtoIsTemplateInstance(fd->parent)) | |
468 { | |
469 fd->llvmDModule = gIR->dmodule; | |
470 | |
471 // function definition | |
472 if (fd->fbody != 0) | |
473 { | |
474 Logger::println("Doing function body for: %s", fd->toChars()); | |
475 assert(fd->llvmIRFunc); | |
476 gIR->functions.push_back(fd->llvmIRFunc); | |
477 | |
478 if (fd->isMain()) | |
479 gIR->emitMain = true; | |
480 | |
481 llvm::BasicBlock* beginbb = new llvm::BasicBlock("entry",func); | |
482 llvm::BasicBlock* endbb = new llvm::BasicBlock("endentry",func); | |
483 | |
484 //assert(gIR->scopes.empty()); | |
485 gIR->scopes.push_back(IRScope(beginbb, endbb)); | |
486 | |
487 // create alloca point | |
488 f->llvmAllocaPoint = new llvm::BitCastInst(llvm::ConstantInt::get(llvm::Type::Int32Ty,0,false),llvm::Type::Int32Ty,"alloca point",gIR->scopebb()); | |
489 gIR->func()->allocapoint = f->llvmAllocaPoint; | |
490 | |
108
288fe1029e1f
[svn r112] Fixed 'case 1,2,3:' style case statements.
lindquist
parents:
102
diff
changeset
|
491 // need result variable? (not nested) |
288fe1029e1f
[svn r112] Fixed 'case 1,2,3:' style case statements.
lindquist
parents:
102
diff
changeset
|
492 if (fd->vresult && !fd->vresult->nestedref) { |
288fe1029e1f
[svn r112] Fixed 'case 1,2,3:' style case statements.
lindquist
parents:
102
diff
changeset
|
493 Logger::println("non-nested vresult value"); |
288fe1029e1f
[svn r112] Fixed 'case 1,2,3:' style case statements.
lindquist
parents:
102
diff
changeset
|
494 fd->vresult->llvmValue = new llvm::AllocaInst(DtoType(fd->vresult->type),"function_vresult",f->llvmAllocaPoint); |
288fe1029e1f
[svn r112] Fixed 'case 1,2,3:' style case statements.
lindquist
parents:
102
diff
changeset
|
495 } |
288fe1029e1f
[svn r112] Fixed 'case 1,2,3:' style case statements.
lindquist
parents:
102
diff
changeset
|
496 |
100 | 497 // give arguments storage |
498 size_t n = Argument::dim(f->parameters); | |
499 for (int i=0; i < n; ++i) { | |
500 Argument* arg = Argument::getNth(f->parameters, i); | |
501 if (arg && arg->vardecl) { | |
502 VarDeclaration* vd = arg->vardecl; | |
503 if (!vd->llvmNeedsStorage || vd->nestedref || vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type)) | |
504 continue; | |
505 llvm::Value* a = vd->llvmValue; | |
506 assert(a); | |
507 std::string s(a->getName()); | |
508 Logger::println("giving argument '%s' storage", s.c_str()); | |
509 s.append("_storage"); | |
510 llvm::Value* v = new llvm::AllocaInst(a->getType(),s,f->llvmAllocaPoint); | |
511 gIR->ir->CreateStore(a,v); | |
512 vd->llvmValue = v; | |
513 } | |
514 else { | |
515 Logger::attention("some unknown argument: %s", arg ? arg->toChars() : 0); | |
516 } | |
517 } | |
518 | |
519 // debug info | |
520 if (global.params.symdebug) DtoDwarfFuncStart(fd); | |
521 | |
522 llvm::Value* parentNested = NULL; | |
523 if (FuncDeclaration* fd2 = fd->toParent()->isFuncDeclaration()) { | |
108
288fe1029e1f
[svn r112] Fixed 'case 1,2,3:' style case statements.
lindquist
parents:
102
diff
changeset
|
524 if (!fd->isStatic()) |
288fe1029e1f
[svn r112] Fixed 'case 1,2,3:' style case statements.
lindquist
parents:
102
diff
changeset
|
525 parentNested = fd2->llvmNested; |
288fe1029e1f
[svn r112] Fixed 'case 1,2,3:' style case statements.
lindquist
parents:
102
diff
changeset
|
526 } |
288fe1029e1f
[svn r112] Fixed 'case 1,2,3:' style case statements.
lindquist
parents:
102
diff
changeset
|
527 |
288fe1029e1f
[svn r112] Fixed 'case 1,2,3:' style case statements.
lindquist
parents:
102
diff
changeset
|
528 // need result variable? (nested) |
288fe1029e1f
[svn r112] Fixed 'case 1,2,3:' style case statements.
lindquist
parents:
102
diff
changeset
|
529 if (fd->vresult && fd->vresult->nestedref) { |
288fe1029e1f
[svn r112] Fixed 'case 1,2,3:' style case statements.
lindquist
parents:
102
diff
changeset
|
530 Logger::println("nested vresult value: %s", fd->vresult->toChars()); |
288fe1029e1f
[svn r112] Fixed 'case 1,2,3:' style case statements.
lindquist
parents:
102
diff
changeset
|
531 fd->llvmNestedVars.insert(fd->vresult); |
100 | 532 } |
533 | |
534 // construct nested variables struct | |
535 if (!fd->llvmNestedVars.empty() || parentNested) { | |
536 std::vector<const llvm::Type*> nestTypes; | |
537 int j = 0; | |
538 if (parentNested) { | |
539 nestTypes.push_back(parentNested->getType()); | |
540 j++; | |
541 } | |
542 for (std::set<VarDeclaration*>::iterator i=fd->llvmNestedVars.begin(); i!=fd->llvmNestedVars.end(); ++i) { | |
543 VarDeclaration* vd = *i; | |
544 vd->llvmNestedIndex = j++; | |
545 if (vd->isParameter()) { | |
546 assert(vd->llvmValue); | |
547 nestTypes.push_back(vd->llvmValue->getType()); | |
548 } | |
549 else { | |
550 nestTypes.push_back(DtoType(vd->type)); | |
551 } | |
552 } | |
553 const llvm::StructType* nestSType = llvm::StructType::get(nestTypes); | |
554 Logger::cout() << "nested var struct has type:" << '\n' << *nestSType; | |
555 fd->llvmNested = new llvm::AllocaInst(nestSType,"nestedvars",f->llvmAllocaPoint); | |
556 if (parentNested) { | |
557 assert(fd->llvmThisVar); | |
558 llvm::Value* ptr = gIR->ir->CreateBitCast(fd->llvmThisVar, parentNested->getType(), "tmp"); | |
559 gIR->ir->CreateStore(ptr, DtoGEPi(fd->llvmNested, 0,0, "tmp")); | |
560 } | |
561 for (std::set<VarDeclaration*>::iterator i=fd->llvmNestedVars.begin(); i!=fd->llvmNestedVars.end(); ++i) { | |
562 VarDeclaration* vd = *i; | |
563 if (vd->isParameter()) { | |
564 gIR->ir->CreateStore(vd->llvmValue, DtoGEPi(fd->llvmNested, 0, vd->llvmNestedIndex, "tmp")); | |
565 vd->llvmValue = fd->llvmNested; | |
566 } | |
567 } | |
568 } | |
569 | |
570 // copy _argptr to a memory location | |
571 if (f->linkage == LINKd && f->varargs == 1) | |
572 { | |
573 llvm::Value* argptrmem = new llvm::AllocaInst(fd->llvmArgPtr->getType(), "_argptrmem", gIR->topallocapoint()); | |
574 new llvm::StoreInst(fd->llvmArgPtr, argptrmem, gIR->scopebb()); | |
575 fd->llvmArgPtr = argptrmem; | |
576 } | |
577 | |
578 // output function body | |
579 fd->fbody->toIR(gIR); | |
580 | |
581 // llvm requires all basic blocks to end with a TerminatorInst but DMD does not put a return statement | |
582 // in automatically, so we do it here. | |
583 if (!fd->isMain()) { | |
584 if (!gIR->scopereturned()) { | |
585 // pass the previous block into this block | |
586 if (global.params.symdebug) DtoDwarfFuncEnd(fd); | |
587 if (func->getReturnType() == llvm::Type::VoidTy) { | |
588 new llvm::ReturnInst(gIR->scopebb()); | |
589 } | |
590 else { | |
591 new llvm::ReturnInst(llvm::UndefValue::get(func->getReturnType()), gIR->scopebb()); | |
592 } | |
593 } | |
594 } | |
595 | |
596 // erase alloca point | |
597 f->llvmAllocaPoint->eraseFromParent(); | |
598 f->llvmAllocaPoint = 0; | |
599 gIR->func()->allocapoint = 0; | |
600 | |
601 gIR->scopes.pop_back(); | |
602 | |
603 // get rid of the endentry block, it's never used | |
604 assert(!func->getBasicBlockList().empty()); | |
605 func->getBasicBlockList().pop_back(); | |
606 | |
607 // if the last block is empty now, it must be unreachable or it's a bug somewhere else | |
608 // would be nice to figure out how to assert that this is correct | |
609 llvm::BasicBlock* lastbb = &func->getBasicBlockList().back(); | |
610 if (lastbb->empty()) { | |
611 if (lastbb->getNumUses() == 0) | |
612 lastbb->eraseFromParent(); | |
613 else { | |
614 new llvm::UnreachableInst(lastbb); | |
615 /*if (func->getReturnType() == llvm::Type::VoidTy) { | |
616 new llvm::ReturnInst(lastbb); | |
617 } | |
618 else { | |
619 new llvm::ReturnInst(llvm::UndefValue::get(func->getReturnType()), lastbb); | |
620 }*/ | |
621 } | |
622 } | |
623 | |
624 gIR->functions.pop_back(); | |
625 } | |
626 } | |
627 } | |
628 | |
629 ////////////////////////////////////////////////////////////////////////////////////////// | |
630 | |
631 void DtoMain() | |
632 { | |
633 // emit main function llvm style | |
634 // int main(int argc, char**argv, char**env); | |
635 | |
636 assert(gIR != 0); | |
637 IRState& ir = *gIR; | |
638 | |
639 assert(ir.emitMain && ir.mainFunc); | |
640 | |
641 // parameter types | |
642 std::vector<const llvm::Type*> pvec; | |
643 pvec.push_back((const llvm::Type*)llvm::Type::Int32Ty); | |
644 const llvm::Type* chPtrType = (const llvm::Type*)llvm::PointerType::get(llvm::Type::Int8Ty); | |
645 pvec.push_back((const llvm::Type*)llvm::PointerType::get(chPtrType)); | |
646 pvec.push_back((const llvm::Type*)llvm::PointerType::get(chPtrType)); | |
647 const llvm::Type* rettype = (const llvm::Type*)llvm::Type::Int32Ty; | |
648 | |
649 llvm::FunctionType* functype = llvm::FunctionType::get(rettype, pvec, false); | |
650 llvm::Function* func = new llvm::Function(functype,llvm::GlobalValue::ExternalLinkage,"main",ir.module); | |
651 | |
652 llvm::BasicBlock* bb = new llvm::BasicBlock("entry",func); | |
653 | |
654 // call static ctors | |
117 | 655 llvm::Function* fn = LLVM_D_GetRuntimeFunction(ir.module,"_moduleCtor"); |
100 | 656 llvm::Instruction* apt = new llvm::CallInst(fn,"",bb); |
657 | |
658 // call user main function | |
659 const llvm::FunctionType* mainty = ir.mainFunc->getFunctionType(); | |
660 llvm::CallInst* call; | |
661 if (mainty->getNumParams() > 0) | |
662 { | |
663 // main with arguments | |
664 assert(mainty->getNumParams() == 1); | |
665 std::vector<llvm::Value*> args; | |
666 llvm::Function* mfn = LLVM_D_GetRuntimeFunction(ir.module,"_d_main_args"); | |
667 | |
668 llvm::Function::arg_iterator argi = func->arg_begin(); | |
669 args.push_back(argi++); | |
670 args.push_back(argi++); | |
671 | |
672 const llvm::Type* at = mainty->getParamType(0)->getContainedType(0); | |
673 llvm::Value* arr = new llvm::AllocaInst(at->getContainedType(1)->getContainedType(0), func->arg_begin(), "argstorage", apt); | |
674 llvm::Value* a = new llvm::AllocaInst(at, "argarray", apt); | |
675 llvm::Value* ptr = DtoGEPi(a,0,0,"tmp",bb); | |
676 llvm::Value* v = args[0]; | |
677 if (v->getType() != DtoSize_t()) | |
678 v = new llvm::ZExtInst(v, DtoSize_t(), "tmp", bb); | |
679 new llvm::StoreInst(v,ptr,bb); | |
680 ptr = DtoGEPi(a,0,1,"tmp",bb); | |
681 new llvm::StoreInst(arr,ptr,bb); | |
682 args.push_back(a); | |
683 new llvm::CallInst(mfn, args.begin(), args.end(), "", bb); | |
684 call = new llvm::CallInst(ir.mainFunc,a,"ret",bb); | |
685 } | |
686 else | |
687 { | |
688 // main with no arguments | |
689 call = new llvm::CallInst(ir.mainFunc,"ret",bb); | |
690 } | |
691 call->setCallingConv(ir.mainFunc->getCallingConv()); | |
692 | |
693 // call static dtors | |
117 | 694 fn = LLVM_D_GetRuntimeFunction(ir.module,"_moduleDtor"); |
100 | 695 new llvm::CallInst(fn,"",bb); |
696 | |
697 // return | |
698 new llvm::ReturnInst(call,bb); | |
699 } | |
700 | |
701 ////////////////////////////////////////////////////////////////////////////////////////// | |
117 | 702 |
703 const llvm::FunctionType* DtoBaseFunctionType(FuncDeclaration* fdecl) | |
704 { | |
705 Dsymbol* parent = fdecl->toParent(); | |
706 ClassDeclaration* cd = parent->isClassDeclaration(); | |
707 assert(cd); | |
708 | |
709 FuncDeclaration* f = fdecl; | |
710 | |
711 while (cd) | |
712 { | |
713 ClassDeclaration* base = cd->baseClass; | |
714 if (!base) | |
715 break; | |
716 FuncDeclaration* f2 = base->findFunc(fdecl->ident, (TypeFunction*)fdecl->type); | |
717 if (f2) { | |
718 f = f2; | |
719 cd = base; | |
720 } | |
721 else | |
722 break; | |
723 } | |
724 | |
725 DtoResolveDsymbol(f); | |
726 return llvm::cast<llvm::FunctionType>(DtoType(f->type)); | |
727 } | |
728 | |
729 ////////////////////////////////////////////////////////////////////////////////////////// |