Mercurial > projects > ldc
annotate gen/toobj.c @ 82:d8dd47ef3973 trunk
[svn r86] Changed the way arguments are given storage. It is now detected if they will need it during semantic passes.
Initial support for debug information. Very limited, but MUCH better than nothing :)
author | lindquist |
---|---|
date | Fri, 02 Nov 2007 01:17:26 +0100 |
parents | 3587401b6eeb |
children | 169711a7126e |
rev | line source |
---|---|
1 | 1 |
2 // Copyright (c) 1999-2004 by Digital Mars | |
3 // All Rights Reserved | |
4 // written by Walter Bright | |
5 // www.digitalmars.com | |
6 // License for redistribution is by either the Artistic License | |
7 // in artistic.txt, or the GNU General Public License in gnu.txt. | |
8 // See the included readme.txt for details. | |
9 | |
10 #include <cstddef> | |
11 #include <iostream> | |
12 #include <fstream> | |
13 | |
40 | 14 #include "gen/llvm.h" |
1 | 15 #include "llvm/Analysis/Verifier.h" |
16 #include "llvm/Bitcode/ReaderWriter.h" | |
17 #include "llvm/Target/TargetMachine.h" | |
18 #include "llvm/Target/TargetMachineRegistry.h" | |
19 | |
20 #include "mars.h" | |
21 #include "module.h" | |
22 #include "mtype.h" | |
23 #include "declaration.h" | |
24 #include "statement.h" | |
25 #include "enum.h" | |
26 #include "aggregate.h" | |
27 #include "init.h" | |
28 #include "attrib.h" | |
29 #include "id.h" | |
30 #include "import.h" | |
31 #include "template.h" | |
18 | 32 #include "scope.h" |
1 | 33 |
4
e116aa1488e6
[svn r8] changed backend includes to always use the gen/<foo>.h prefix
lindquist
parents:
1
diff
changeset
|
34 #include "gen/irstate.h" |
e116aa1488e6
[svn r8] changed backend includes to always use the gen/<foo>.h prefix
lindquist
parents:
1
diff
changeset
|
35 #include "gen/elem.h" |
e116aa1488e6
[svn r8] changed backend includes to always use the gen/<foo>.h prefix
lindquist
parents:
1
diff
changeset
|
36 #include "gen/logger.h" |
e116aa1488e6
[svn r8] changed backend includes to always use the gen/<foo>.h prefix
lindquist
parents:
1
diff
changeset
|
37 #include "gen/tollvm.h" |
64
b688ad419f8c
[svn r68] Added support for multi-dimensional static arrays.
lindquist
parents:
63
diff
changeset
|
38 #include "gen/arrays.h" |
82
d8dd47ef3973
[svn r86] Changed the way arguments are given storage. It is now detected if they will need it during semantic passes.
lindquist
parents:
81
diff
changeset
|
39 #include "gen/todebug.h" |
1 | 40 |
41 ////////////////////////////////////////////////////////////////////////////////////////// | |
42 | |
43 void | |
44 Module::genobjfile() | |
45 { | |
46 Logger::cout() << "Generating module: " << (md ? md->toChars() : toChars()) << '\n'; | |
47 LOG_SCOPE; | |
48 | |
6 | 49 // start by deleting the old object file |
1 | 50 deleteObjFile(); |
51 | |
18 | 52 // create a new ir state |
1 | 53 IRState ir; |
54 gIR = &ir; | |
55 ir.dmodule = this; | |
56 | |
6 | 57 // name the module |
1 | 58 std::string mname(toChars()); |
59 if (md != 0) | |
60 mname = md->toChars(); | |
61 ir.module = new llvm::Module(mname); | |
62 | |
6 | 63 // set target stuff |
1 | 64 std::string target_triple(global.params.tt_arch); |
65 target_triple.append(global.params.tt_os); | |
66 ir.module->setTargetTriple(target_triple); | |
67 ir.module->setDataLayout(global.params.data_layout); | |
68 | |
73 | 69 // heavily inspired by tools/llc/llc.cpp:200-230 |
70 const llvm::TargetMachineRegistry::Entry* targetEntry; | |
71 std::string targetError; | |
72 targetEntry = llvm::TargetMachineRegistry::getClosestStaticTargetForModule(*ir.module, targetError); | |
73 assert(targetEntry && "Failed to find a static target for module"); | |
74 std::auto_ptr<llvm::TargetMachine> targetPtr(targetEntry->CtorFn(*ir.module, "")); // TODO: replace "" with features | |
75 assert(targetPtr.get() && "Could not allocate target machine!"); | |
76 llvm::TargetMachine &targetMachine = *targetPtr.get(); | |
77 gTargetData = targetMachine.getTargetData(); | |
1 | 78 |
82
d8dd47ef3973
[svn r86] Changed the way arguments are given storage. It is now detected if they will need it during semantic passes.
lindquist
parents:
81
diff
changeset
|
79 // debug info |
d8dd47ef3973
[svn r86] Changed the way arguments are given storage. It is now detected if they will need it during semantic passes.
lindquist
parents:
81
diff
changeset
|
80 if (global.params.symdebug) { |
d8dd47ef3973
[svn r86] Changed the way arguments are given storage. It is now detected if they will need it during semantic passes.
lindquist
parents:
81
diff
changeset
|
81 RegisterDwarfSymbols(ir.module); |
d8dd47ef3973
[svn r86] Changed the way arguments are given storage. It is now detected if they will need it during semantic passes.
lindquist
parents:
81
diff
changeset
|
82 ir.dwarfCompileUnit = DtoDwarfCompileUnit(this); |
d8dd47ef3973
[svn r86] Changed the way arguments are given storage. It is now detected if they will need it during semantic passes.
lindquist
parents:
81
diff
changeset
|
83 } |
d8dd47ef3973
[svn r86] Changed the way arguments are given storage. It is now detected if they will need it during semantic passes.
lindquist
parents:
81
diff
changeset
|
84 |
6 | 85 // process module members |
1 | 86 for (int k=0; k < members->dim; k++) { |
87 Dsymbol* dsym = (Dsymbol*)(members->data[k]); | |
88 assert(dsym); | |
89 dsym->toObjFile(); | |
90 } | |
91 | |
92 gTargetData = 0; | |
93 | |
11
d3ee9efe20e2
[svn r15] * Fixed a bunch problems with virtual calls. Seems I did some rather poor testing.
lindquist
parents:
10
diff
changeset
|
94 // emit the llvm main function if necessary |
d3ee9efe20e2
[svn r15] * Fixed a bunch problems with virtual calls. Seems I did some rather poor testing.
lindquist
parents:
10
diff
changeset
|
95 if (ir.emitMain) { |
81
3587401b6eeb
[svn r85] Fixed: if a return statement appeared in the try block of a nested try-finally, only the inner-most finally block would be executed.
lindquist
parents:
77
diff
changeset
|
96 DtoMain(); |
11
d3ee9efe20e2
[svn r15] * Fixed a bunch problems with virtual calls. Seems I did some rather poor testing.
lindquist
parents:
10
diff
changeset
|
97 } |
d3ee9efe20e2
[svn r15] * Fixed a bunch problems with virtual calls. Seems I did some rather poor testing.
lindquist
parents:
10
diff
changeset
|
98 |
6 | 99 // verify the llvm |
31
2841234d2aea
[svn r35] * Attributes on struct fields/methods now work
lindquist
parents:
28
diff
changeset
|
100 if (!global.params.novalidate) { |
2841234d2aea
[svn r35] * Attributes on struct fields/methods now work
lindquist
parents:
28
diff
changeset
|
101 std::string verifyErr; |
2841234d2aea
[svn r35] * Attributes on struct fields/methods now work
lindquist
parents:
28
diff
changeset
|
102 Logger::println("Verifying module..."); |
2841234d2aea
[svn r35] * Attributes on struct fields/methods now work
lindquist
parents:
28
diff
changeset
|
103 if (llvm::verifyModule(*ir.module,llvm::ReturnStatusAction,&verifyErr)) |
2841234d2aea
[svn r35] * Attributes on struct fields/methods now work
lindquist
parents:
28
diff
changeset
|
104 { |
2841234d2aea
[svn r35] * Attributes on struct fields/methods now work
lindquist
parents:
28
diff
changeset
|
105 error("%s", verifyErr.c_str()); |
2841234d2aea
[svn r35] * Attributes on struct fields/methods now work
lindquist
parents:
28
diff
changeset
|
106 fatal(); |
2841234d2aea
[svn r35] * Attributes on struct fields/methods now work
lindquist
parents:
28
diff
changeset
|
107 } |
2841234d2aea
[svn r35] * Attributes on struct fields/methods now work
lindquist
parents:
28
diff
changeset
|
108 else { |
2841234d2aea
[svn r35] * Attributes on struct fields/methods now work
lindquist
parents:
28
diff
changeset
|
109 Logger::println("Verification passed!"); |
2841234d2aea
[svn r35] * Attributes on struct fields/methods now work
lindquist
parents:
28
diff
changeset
|
110 } |
1 | 111 } |
112 | |
113 // run passes | |
114 // TODO | |
115 | |
52 | 116 // write bytecode |
117 { | |
118 Logger::println("Writing LLVM bitcode\n"); | |
119 std::ofstream bos(bcfile->name->toChars(), std::ios::binary); | |
120 llvm::WriteBitcodeToFile(ir.module, bos); | |
121 } | |
1 | 122 |
52 | 123 // disassemble ? |
124 if (global.params.disassemble) { | |
125 Logger::println("Writing LLVM asm to: %s\n", llfile->name->toChars()); | |
126 std::ofstream aos(llfile->name->toChars()); | |
127 ir.module->print(aos); | |
128 } | |
1 | 129 |
130 delete ir.module; | |
131 gIR = NULL; | |
132 } | |
133 | |
134 /* ================================================================== */ | |
135 | |
136 // Put out instance of ModuleInfo for this Module | |
137 | |
138 void Module::genmoduleinfo() | |
139 { | |
140 } | |
141 | |
142 /* ================================================================== */ | |
143 | |
144 void Dsymbol::toObjFile() | |
145 { | |
38
27b2f40bdb58
[svn r42] Disabled the extensive logging by default. Use the -vv flag to get it back.
lindquist
parents:
31
diff
changeset
|
146 Logger::println("Ignoring Dsymbol::toObjFile for %s", toChars()); |
1 | 147 } |
148 | |
149 /* ================================================================== */ | |
150 | |
151 void Declaration::toObjFile() | |
152 { | |
38
27b2f40bdb58
[svn r42] Disabled the extensive logging by default. Use the -vv flag to get it back.
lindquist
parents:
31
diff
changeset
|
153 Logger::println("Ignoring Declaration::toObjFile for %s", toChars()); |
1 | 154 } |
155 | |
156 /* ================================================================== */ | |
157 | |
158 void InterfaceDeclaration::toObjFile() | |
159 { | |
38
27b2f40bdb58
[svn r42] Disabled the extensive logging by default. Use the -vv flag to get it back.
lindquist
parents:
31
diff
changeset
|
160 Logger::println("Ignoring InterfaceDeclaration::toObjFile for %s", toChars()); |
1 | 161 } |
162 | |
163 /* ================================================================== */ | |
164 | |
165 void StructDeclaration::toObjFile() | |
166 { | |
81
3587401b6eeb
[svn r85] Fixed: if a return statement appeared in the try block of a nested try-finally, only the inner-most finally block would be executed.
lindquist
parents:
77
diff
changeset
|
167 TypeStruct* ts = (TypeStruct*)DtoDType(type); |
1 | 168 if (llvmType != 0) |
169 return; | |
170 | |
171 static int sdi = 0; | |
172 Logger::print("StructDeclaration::toObjFile(%d): %s\n", sdi++, toChars()); | |
173 LOG_SCOPE; | |
174 | |
175 gIR->structs.push_back(IRStruct(ts)); | |
176 | |
177 for (int k=0; k < members->dim; k++) { | |
178 Dsymbol* dsym = (Dsymbol*)(members->data[k]); | |
31
2841234d2aea
[svn r35] * Attributes on struct fields/methods now work
lindquist
parents:
28
diff
changeset
|
179 dsym->toObjFile(); |
1 | 180 } |
181 | |
73 | 182 Logger::println("doing struct fields"); |
183 | |
184 llvm::StructType* structtype = 0; | |
185 std::vector<llvm::Constant*> fieldinits; | |
186 | |
187 if (gIR->topstruct().offsets.empty()) | |
188 { | |
189 std::vector<const llvm::Type*> fieldtypes; | |
190 Logger::println("has no fields"); | |
191 fieldtypes.push_back(llvm::Type::Int8Ty); | |
192 fieldinits.push_back(llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false)); | |
193 structtype = llvm::StructType::get(fieldtypes); | |
194 } | |
195 else | |
23 | 196 { |
73 | 197 Logger::println("has fields"); |
198 std::vector<const llvm::Type*> fieldtypes; | |
199 unsigned prevsize = (unsigned)-1; | |
200 unsigned lastoffset = (unsigned)-1; | |
201 const llvm::Type* fieldtype = NULL; | |
202 llvm::Constant* fieldinit = NULL; | |
203 size_t fieldpad = 0; | |
204 int idx = 0; | |
205 for (IRStruct::OffsetMap::iterator i=gIR->topstruct().offsets.begin(); i!=gIR->topstruct().offsets.end(); ++i) { | |
206 // first iteration | |
207 if (lastoffset == (unsigned)-1) { | |
208 lastoffset = i->first; | |
209 assert(lastoffset == 0); | |
81
3587401b6eeb
[svn r85] Fixed: if a return statement appeared in the try block of a nested try-finally, only the inner-most finally block would be executed.
lindquist
parents:
77
diff
changeset
|
210 fieldtype = DtoType(i->second.var->type); |
73 | 211 fieldinit = i->second.init; |
212 prevsize = gTargetData->getTypeSize(fieldtype); | |
213 i->second.var->llvmFieldIndex = idx; | |
214 } | |
215 // colliding offset? | |
216 else if (lastoffset == i->first) { | |
81
3587401b6eeb
[svn r85] Fixed: if a return statement appeared in the try block of a nested try-finally, only the inner-most finally block would be executed.
lindquist
parents:
77
diff
changeset
|
217 const llvm::Type* t = DtoType(i->second.var->type); |
73 | 218 size_t s = gTargetData->getTypeSize(t); |
219 if (s > prevsize) { | |
77
714057ff2dbb
[svn r81] Fixed: Union support was very buggy. Should be fairly solid now.
lindquist
parents:
74
diff
changeset
|
220 fieldpad += s - prevsize; |
73 | 221 prevsize = s; |
222 } | |
223 llvmHasUnions = true; | |
224 i->second.var->llvmFieldIndex = idx; | |
225 } | |
226 // intersecting offset? | |
227 else if (i->first < (lastoffset + prevsize)) { | |
81
3587401b6eeb
[svn r85] Fixed: if a return statement appeared in the try block of a nested try-finally, only the inner-most finally block would be executed.
lindquist
parents:
77
diff
changeset
|
228 const llvm::Type* t = DtoType(i->second.var->type); |
73 | 229 size_t s = gTargetData->getTypeSize(t); |
230 assert((i->first + s) <= (lastoffset + prevsize)); // this holds because all types are aligned to their size | |
231 llvmHasUnions = true; | |
232 i->second.var->llvmFieldIndex = idx; | |
233 i->second.var->llvmFieldIndexOffset = (i->first - lastoffset) / s; | |
234 } | |
235 // fresh offset | |
236 else { | |
237 // commit the field | |
238 fieldtypes.push_back(fieldtype); | |
239 fieldinits.push_back(fieldinit); | |
240 if (fieldpad) { | |
241 // match up with below | |
242 std::vector<llvm::Constant*> vals(fieldpad, llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false)); | |
243 llvm::Constant* c = llvm::ConstantArray::get(llvm::ArrayType::get(llvm::Type::Int8Ty, fieldpad), vals); | |
244 fieldtypes.push_back(c->getType()); | |
245 fieldinits.push_back(c); | |
246 idx++; | |
247 } | |
248 | |
249 idx++; | |
250 | |
251 // start new | |
252 lastoffset = i->first; | |
81
3587401b6eeb
[svn r85] Fixed: if a return statement appeared in the try block of a nested try-finally, only the inner-most finally block would be executed.
lindquist
parents:
77
diff
changeset
|
253 fieldtype = DtoType(i->second.var->type); |
73 | 254 fieldinit = i->second.init; |
255 prevsize = gTargetData->getTypeSize(fieldtype); | |
256 i->second.var->llvmFieldIndex = idx; | |
257 fieldpad = 0; | |
258 } | |
259 } | |
260 fieldtypes.push_back(fieldtype); | |
261 fieldinits.push_back(fieldinit); | |
262 if (fieldpad) { | |
263 // match up with above | |
264 std::vector<llvm::Constant*> vals(fieldpad, llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false)); | |
265 llvm::Constant* c = llvm::ConstantArray::get(llvm::ArrayType::get(llvm::Type::Int8Ty, fieldpad), vals); | |
266 fieldtypes.push_back(c->getType()); | |
267 fieldinits.push_back(c); | |
268 } | |
269 | |
270 Logger::println("creating struct type"); | |
271 structtype = llvm::StructType::get(fieldtypes); | |
23 | 272 } |
273 | |
1 | 274 // refine abstract types for stuff like: struct S{S* next;} |
275 if (gIR->topstruct().recty != 0) | |
276 { | |
277 llvm::PATypeHolder& pa = gIR->topstruct().recty; | |
278 llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(structtype); | |
279 structtype = llvm::cast<llvm::StructType>(pa.get()); | |
280 } | |
281 | |
282 ts->llvmType = structtype; | |
283 llvmType = structtype; | |
284 | |
285 if (parent->isModule()) { | |
286 gIR->module->addTypeName(mangle(),ts->llvmType); | |
287 } | |
288 | |
289 // generate static data | |
290 llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage; | |
291 llvm::Constant* _init = 0; | |
292 | |
293 // always generate the constant initalizer | |
294 if (!zeroInit) { | |
295 Logger::println("Not zero initialized"); | |
73 | 296 //assert(tk == gIR->gIR->topstruct()().size()); |
1 | 297 #ifndef LLVMD_NO_LOGGER |
73 | 298 Logger::cout() << "struct type: " << *structtype << '\n'; |
299 for (size_t k=0; k<fieldinits.size(); ++k) { | |
1 | 300 Logger::cout() << "Type:" << '\n'; |
73 | 301 Logger::cout() << *fieldinits[k]->getType() << '\n'; |
1 | 302 Logger::cout() << "Value:" << '\n'; |
73 | 303 Logger::cout() << *fieldinits[k] << '\n'; |
1 | 304 } |
305 Logger::cout() << "Initializer printed" << '\n'; | |
306 #endif | |
73 | 307 llvmInitZ = llvm::ConstantStruct::get(structtype,fieldinits); |
1 | 308 } |
309 else { | |
310 Logger::println("Zero initialized"); | |
311 llvmInitZ = llvm::ConstantAggregateZero::get(structtype); | |
312 } | |
313 | |
314 // only provide the constant initializer for the defining module | |
315 if (getModule() == gIR->dmodule) | |
316 { | |
317 _init = llvmInitZ; | |
318 } | |
319 | |
73 | 320 std::string initname("_D"); |
321 initname.append(mangle()); | |
322 initname.append("6__initZ"); | |
1 | 323 llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType, true, _linkage, _init, initname, gIR->module); |
324 ts->llvmInit = initvar; | |
325 | |
31
2841234d2aea
[svn r35] * Attributes on struct fields/methods now work
lindquist
parents:
28
diff
changeset
|
326 // generate member function definitions |
2841234d2aea
[svn r35] * Attributes on struct fields/methods now work
lindquist
parents:
28
diff
changeset
|
327 gIR->topstruct().queueFuncs = false; |
73 | 328 IRStruct::FuncDeclVector& mfs = gIR->topstruct().funcs; |
1 | 329 size_t n = mfs.size(); |
330 for (size_t i=0; i<n; ++i) { | |
331 mfs[i]->toObjFile(); | |
332 } | |
333 | |
334 llvmDModule = gIR->dmodule; | |
335 | |
336 gIR->structs.pop_back(); | |
337 | |
338 // generate typeinfo | |
73 | 339 if (getModule() == gIR->dmodule && llvmInternal != LLVMnotypeinfo) |
72 | 340 type->getTypeInfo(NULL); |
1 | 341 } |
342 | |
343 /* ================================================================== */ | |
344 | |
77
714057ff2dbb
[svn r81] Fixed: Union support was very buggy. Should be fairly solid now.
lindquist
parents:
74
diff
changeset
|
345 static unsigned LLVM_ClassOffsetToIndex(ClassDeclaration* cd, unsigned os, unsigned& idx) |
714057ff2dbb
[svn r81] Fixed: Union support was very buggy. Should be fairly solid now.
lindquist
parents:
74
diff
changeset
|
346 { |
714057ff2dbb
[svn r81] Fixed: Union support was very buggy. Should be fairly solid now.
lindquist
parents:
74
diff
changeset
|
347 // start at the bottom of the inheritance chain |
714057ff2dbb
[svn r81] Fixed: Union support was very buggy. Should be fairly solid now.
lindquist
parents:
74
diff
changeset
|
348 if (cd->baseClass != 0) { |
714057ff2dbb
[svn r81] Fixed: Union support was very buggy. Should be fairly solid now.
lindquist
parents:
74
diff
changeset
|
349 unsigned o = LLVM_ClassOffsetToIndex(cd->baseClass, os, idx); |
714057ff2dbb
[svn r81] Fixed: Union support was very buggy. Should be fairly solid now.
lindquist
parents:
74
diff
changeset
|
350 if (o != (unsigned)-1) |
714057ff2dbb
[svn r81] Fixed: Union support was very buggy. Should be fairly solid now.
lindquist
parents:
74
diff
changeset
|
351 return o; |
714057ff2dbb
[svn r81] Fixed: Union support was very buggy. Should be fairly solid now.
lindquist
parents:
74
diff
changeset
|
352 } |
714057ff2dbb
[svn r81] Fixed: Union support was very buggy. Should be fairly solid now.
lindquist
parents:
74
diff
changeset
|
353 |
714057ff2dbb
[svn r81] Fixed: Union support was very buggy. Should be fairly solid now.
lindquist
parents:
74
diff
changeset
|
354 // check this class |
714057ff2dbb
[svn r81] Fixed: Union support was very buggy. Should be fairly solid now.
lindquist
parents:
74
diff
changeset
|
355 unsigned i; |
714057ff2dbb
[svn r81] Fixed: Union support was very buggy. Should be fairly solid now.
lindquist
parents:
74
diff
changeset
|
356 for (i=0; i<cd->fields.dim; ++i) { |
714057ff2dbb
[svn r81] Fixed: Union support was very buggy. Should be fairly solid now.
lindquist
parents:
74
diff
changeset
|
357 VarDeclaration* vd = (VarDeclaration*)cd->fields.data[i]; |
714057ff2dbb
[svn r81] Fixed: Union support was very buggy. Should be fairly solid now.
lindquist
parents:
74
diff
changeset
|
358 if (os == vd->offset) |
714057ff2dbb
[svn r81] Fixed: Union support was very buggy. Should be fairly solid now.
lindquist
parents:
74
diff
changeset
|
359 return i+idx; |
714057ff2dbb
[svn r81] Fixed: Union support was very buggy. Should be fairly solid now.
lindquist
parents:
74
diff
changeset
|
360 } |
714057ff2dbb
[svn r81] Fixed: Union support was very buggy. Should be fairly solid now.
lindquist
parents:
74
diff
changeset
|
361 idx += i; |
714057ff2dbb
[svn r81] Fixed: Union support was very buggy. Should be fairly solid now.
lindquist
parents:
74
diff
changeset
|
362 |
714057ff2dbb
[svn r81] Fixed: Union support was very buggy. Should be fairly solid now.
lindquist
parents:
74
diff
changeset
|
363 return (unsigned)-1; |
714057ff2dbb
[svn r81] Fixed: Union support was very buggy. Should be fairly solid now.
lindquist
parents:
74
diff
changeset
|
364 } |
714057ff2dbb
[svn r81] Fixed: Union support was very buggy. Should be fairly solid now.
lindquist
parents:
74
diff
changeset
|
365 |
714057ff2dbb
[svn r81] Fixed: Union support was very buggy. Should be fairly solid now.
lindquist
parents:
74
diff
changeset
|
366 void ClassDeclaration::offsetToIndex(Type* t, unsigned os, std::vector<unsigned>& result) |
714057ff2dbb
[svn r81] Fixed: Union support was very buggy. Should be fairly solid now.
lindquist
parents:
74
diff
changeset
|
367 { |
714057ff2dbb
[svn r81] Fixed: Union support was very buggy. Should be fairly solid now.
lindquist
parents:
74
diff
changeset
|
368 unsigned idx = 0; |
714057ff2dbb
[svn r81] Fixed: Union support was very buggy. Should be fairly solid now.
lindquist
parents:
74
diff
changeset
|
369 unsigned r = LLVM_ClassOffsetToIndex(this, os, idx); |
714057ff2dbb
[svn r81] Fixed: Union support was very buggy. Should be fairly solid now.
lindquist
parents:
74
diff
changeset
|
370 assert(r != (unsigned)-1 && "Offset not found in any aggregate field"); |
714057ff2dbb
[svn r81] Fixed: Union support was very buggy. Should be fairly solid now.
lindquist
parents:
74
diff
changeset
|
371 result.push_back(r+1); // vtable is 0 |
714057ff2dbb
[svn r81] Fixed: Union support was very buggy. Should be fairly solid now.
lindquist
parents:
74
diff
changeset
|
372 } |
714057ff2dbb
[svn r81] Fixed: Union support was very buggy. Should be fairly solid now.
lindquist
parents:
74
diff
changeset
|
373 |
714057ff2dbb
[svn r81] Fixed: Union support was very buggy. Should be fairly solid now.
lindquist
parents:
74
diff
changeset
|
374 /* ================================================================== */ |
714057ff2dbb
[svn r81] Fixed: Union support was very buggy. Should be fairly solid now.
lindquist
parents:
74
diff
changeset
|
375 |
1 | 376 static void LLVM_AddBaseClassData(BaseClasses* bcs) |
377 { | |
378 // add base class data members first | |
379 for (int j=0; j<bcs->dim; j++) | |
380 { | |
381 BaseClass* bc = (BaseClass*)(bcs->data[j]); | |
382 assert(bc); | |
40 | 383 Logger::println("Adding base class members of %s", bc->base->toChars()); |
384 LOG_SCOPE; | |
385 | |
1 | 386 LLVM_AddBaseClassData(&bc->base->baseclasses); |
387 for (int k=0; k < bc->base->members->dim; k++) { | |
388 Dsymbol* dsym = (Dsymbol*)(bc->base->members->data[k]); | |
389 if (dsym->isVarDeclaration()) | |
390 { | |
391 dsym->toObjFile(); | |
392 } | |
393 } | |
394 } | |
395 } | |
396 | |
397 void ClassDeclaration::toObjFile() | |
398 { | |
81
3587401b6eeb
[svn r85] Fixed: if a return statement appeared in the try block of a nested try-finally, only the inner-most finally block would be executed.
lindquist
parents:
77
diff
changeset
|
399 TypeClass* ts = (TypeClass*)DtoDType(type); |
1 | 400 if (ts->llvmType != 0 || llvmInProgress) |
401 return; | |
402 | |
403 llvmInProgress = true; | |
404 | |
405 static int fdi = 0; | |
406 Logger::print("ClassDeclaration::toObjFile(%d): %s\n", fdi++, toChars()); | |
407 LOG_SCOPE; | |
408 | |
6 | 409 gIR->structs.push_back(IRStruct(ts)); |
1 | 410 gIR->classes.push_back(this); |
411 | |
412 // add vtable | |
9 | 413 llvm::PATypeHolder pa = llvm::OpaqueType::get(); |
414 const llvm::Type* vtabty = llvm::PointerType::get(pa); | |
73 | 415 |
416 std::vector<const llvm::Type*> fieldtypes; | |
417 fieldtypes.push_back(vtabty); | |
418 | |
419 std::vector<llvm::Constant*> fieldinits; | |
420 fieldinits.push_back(0); | |
1 | 421 |
422 // base classes first | |
423 LLVM_AddBaseClassData(&baseclasses); | |
424 | |
425 // then add own members | |
426 for (int k=0; k < members->dim; k++) { | |
427 Dsymbol* dsym = (Dsymbol*)(members->data[k]); | |
428 dsym->toObjFile(); | |
429 } | |
430 | |
73 | 431 // fill out fieldtypes/inits |
432 for (IRStruct::OffsetMap::iterator i=gIR->topstruct().offsets.begin(); i!=gIR->topstruct().offsets.end(); ++i) { | |
81
3587401b6eeb
[svn r85] Fixed: if a return statement appeared in the try block of a nested try-finally, only the inner-most finally block would be executed.
lindquist
parents:
77
diff
changeset
|
433 fieldtypes.push_back(DtoType(i->second.var->type)); |
73 | 434 fieldinits.push_back(i->second.init); |
435 } | |
436 | |
437 llvm::StructType* structtype = llvm::StructType::get(fieldtypes); | |
6 | 438 // refine abstract types for stuff like: class C {C next;} |
439 if (gIR->topstruct().recty != 0) | |
440 { | |
441 llvm::PATypeHolder& pa = gIR->topstruct().recty; | |
442 llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(structtype); | |
443 structtype = llvm::cast<llvm::StructType>(pa.get()); | |
444 } | |
445 | |
1 | 446 ts->llvmType = structtype; |
447 llvmType = structtype; | |
448 | |
54
28e99b04a132
[svn r58] Fixed cond expression resulting in a non-basic type.
lindquist
parents:
52
diff
changeset
|
449 bool needs_definition = false; |
1 | 450 if (parent->isModule()) { |
451 gIR->module->addTypeName(mangle(),ts->llvmType); | |
54
28e99b04a132
[svn r58] Fixed cond expression resulting in a non-basic type.
lindquist
parents:
52
diff
changeset
|
452 needs_definition = (getModule() == gIR->dmodule); |
1 | 453 } |
454 else { | |
455 assert(0 && "class parent is not a module"); | |
456 } | |
457 | |
9 | 458 // generate vtable |
459 llvm::GlobalVariable* svtblVar = 0; | |
460 std::vector<llvm::Constant*> sinits; | |
461 std::vector<const llvm::Type*> sinits_ty; | |
462 sinits.reserve(vtbl.dim); | |
463 sinits_ty.reserve(vtbl.dim); | |
464 | |
465 for (int k=0; k < vtbl.dim; k++) | |
466 { | |
467 Dsymbol* dsym = (Dsymbol*)vtbl.data[k]; | |
468 assert(dsym); | |
469 //Logger::cout() << "vtblsym: " << dsym->toChars() << '\n'; | |
470 | |
471 if (FuncDeclaration* fd = dsym->isFuncDeclaration()) { | |
472 fd->toObjFile(); | |
11
d3ee9efe20e2
[svn r15] * Fixed a bunch problems with virtual calls. Seems I did some rather poor testing.
lindquist
parents:
10
diff
changeset
|
473 assert(fd->llvmValue); |
9 | 474 llvm::Constant* c = llvm::cast<llvm::Constant>(fd->llvmValue); |
475 sinits.push_back(c); | |
476 sinits_ty.push_back(c->getType()); | |
477 } | |
478 else if (ClassDeclaration* cd = dsym->isClassDeclaration()) { | |
479 const llvm::Type* cty = llvm::PointerType::get(llvm::Type::Int8Ty); | |
480 llvm::Constant* c = llvm::Constant::getNullValue(cty); | |
481 sinits.push_back(c); | |
482 sinits_ty.push_back(cty); | |
483 } | |
484 else | |
485 assert(0); | |
486 } | |
487 | |
488 const llvm::StructType* svtbl_ty = 0; | |
489 if (!sinits.empty()) | |
490 { | |
491 llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage; | |
492 | |
52 | 493 std::string varname("_D"); |
494 varname.append(mangle()); | |
495 varname.append("6__vtblZ"); | |
496 | |
9 | 497 std::string styname(mangle()); |
498 styname.append("__vtblTy"); | |
499 | |
500 svtbl_ty = llvm::StructType::get(sinits_ty); | |
501 gIR->module->addTypeName(styname, svtbl_ty); | |
502 svtblVar = new llvm::GlobalVariable(svtbl_ty, true, _linkage, 0, varname, gIR->module); | |
503 | |
54
28e99b04a132
[svn r58] Fixed cond expression resulting in a non-basic type.
lindquist
parents:
52
diff
changeset
|
504 llvmConstVtbl = llvm::cast<llvm::ConstantStruct>(llvm::ConstantStruct::get(svtbl_ty, sinits)); |
28e99b04a132
[svn r58] Fixed cond expression resulting in a non-basic type.
lindquist
parents:
52
diff
changeset
|
505 if (needs_definition) |
28e99b04a132
[svn r58] Fixed cond expression resulting in a non-basic type.
lindquist
parents:
52
diff
changeset
|
506 svtblVar->setInitializer(llvmConstVtbl); |
9 | 507 llvmVtbl = svtblVar; |
508 } | |
509 | |
510 //////////////////////////////////////////////////////////////////////////////// | |
511 | |
512 // refine for final vtable type | |
513 llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(svtbl_ty); | |
514 svtbl_ty = llvm::cast<llvm::StructType>(pa.get()); | |
515 structtype = llvm::cast<llvm::StructType>(gIR->topstruct().recty.get()); | |
516 ts->llvmType = structtype; | |
517 llvmType = structtype; | |
518 | |
519 // generate initializer | |
520 llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage; | |
521 llvm::Constant* _init = 0; | |
522 | |
523 // first field is always the vtable | |
524 assert(svtblVar != 0); | |
73 | 525 fieldinits[0] = svtblVar; |
9 | 526 |
73 | 527 llvmInitZ = _init = llvm::ConstantStruct::get(structtype,fieldinits); |
9 | 528 assert(_init); |
52 | 529 |
530 std::string initname("_D"); | |
531 initname.append(mangle()); | |
532 initname.append("6__initZ"); | |
11
d3ee9efe20e2
[svn r15] * Fixed a bunch problems with virtual calls. Seems I did some rather poor testing.
lindquist
parents:
10
diff
changeset
|
533 //Logger::cout() << *_init << '\n'; |
54
28e99b04a132
[svn r58] Fixed cond expression resulting in a non-basic type.
lindquist
parents:
52
diff
changeset
|
534 llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType, true, _linkage, NULL, initname, gIR->module); |
9 | 535 ts->llvmInit = initvar; |
536 | |
54
28e99b04a132
[svn r58] Fixed cond expression resulting in a non-basic type.
lindquist
parents:
52
diff
changeset
|
537 if (needs_definition) { |
28e99b04a132
[svn r58] Fixed cond expression resulting in a non-basic type.
lindquist
parents:
52
diff
changeset
|
538 initvar->setInitializer(_init); |
28e99b04a132
[svn r58] Fixed cond expression resulting in a non-basic type.
lindquist
parents:
52
diff
changeset
|
539 // generate member functions |
28e99b04a132
[svn r58] Fixed cond expression resulting in a non-basic type.
lindquist
parents:
52
diff
changeset
|
540 gIR->topstruct().queueFuncs = false; |
73 | 541 IRStruct::FuncDeclVector& mfs = gIR->topstruct().funcs; |
54
28e99b04a132
[svn r58] Fixed cond expression resulting in a non-basic type.
lindquist
parents:
52
diff
changeset
|
542 size_t n = mfs.size(); |
28e99b04a132
[svn r58] Fixed cond expression resulting in a non-basic type.
lindquist
parents:
52
diff
changeset
|
543 for (size_t i=0; i<n; ++i) { |
28e99b04a132
[svn r58] Fixed cond expression resulting in a non-basic type.
lindquist
parents:
52
diff
changeset
|
544 mfs[i]->toObjFile(); |
28e99b04a132
[svn r58] Fixed cond expression resulting in a non-basic type.
lindquist
parents:
52
diff
changeset
|
545 } |
1 | 546 } |
547 | |
548 gIR->classes.pop_back(); | |
549 gIR->structs.pop_back(); | |
550 | |
551 llvmInProgress = false; | |
552 } | |
553 | |
554 /****************************************** | |
555 * Get offset of base class's vtbl[] initializer from start of csym. | |
556 * Returns ~0 if not this csym. | |
557 */ | |
558 | |
559 unsigned ClassDeclaration::baseVtblOffset(BaseClass *bc) | |
560 { | |
561 return ~0; | |
562 } | |
563 | |
564 /* ================================================================== */ | |
565 | |
566 void VarDeclaration::toObjFile() | |
567 { | |
40 | 568 Logger::print("VarDeclaration::toObjFile(): %s | %s\n", toChars(), type->toChars()); |
1 | 569 LOG_SCOPE; |
570 llvm::Module* M = gIR->module; | |
571 | |
572 // global variable or magic | |
40 | 573 if (isDataseg() || parent->isModule()) |
1 | 574 { |
40 | 575 if (llvmTouched) return; |
576 else llvmTouched = true; | |
577 | |
1 | 578 bool _isconst = isConst(); |
26
99737f94abfb
[svn r30] * Fixed static function-local variables.
lindquist
parents:
24
diff
changeset
|
579 |
99737f94abfb
[svn r30] * Fixed static function-local variables.
lindquist
parents:
24
diff
changeset
|
580 llvm::GlobalValue::LinkageTypes _linkage; |
52 | 581 if (parent && parent->isFuncDeclaration()) |
26
99737f94abfb
[svn r30] * Fixed static function-local variables.
lindquist
parents:
24
diff
changeset
|
582 _linkage = llvm::GlobalValue::InternalLinkage; |
99737f94abfb
[svn r30] * Fixed static function-local variables.
lindquist
parents:
24
diff
changeset
|
583 else |
81
3587401b6eeb
[svn r85] Fixed: if a return statement appeared in the try block of a nested try-finally, only the inner-most finally block would be executed.
lindquist
parents:
77
diff
changeset
|
584 _linkage = DtoLinkage(protection, storage_class); |
26
99737f94abfb
[svn r30] * Fixed static function-local variables.
lindquist
parents:
24
diff
changeset
|
585 |
81
3587401b6eeb
[svn r85] Fixed: if a return statement appeared in the try block of a nested try-finally, only the inner-most finally block would be executed.
lindquist
parents:
77
diff
changeset
|
586 Type* t = DtoDType(type); |
40 | 587 |
81
3587401b6eeb
[svn r85] Fixed: if a return statement appeared in the try block of a nested try-finally, only the inner-most finally block would be executed.
lindquist
parents:
77
diff
changeset
|
588 const llvm::Type* _type = DtoType(t); |
21
8d45266bbabe
[svn r25] * Fixed a lot of problems with string literals
lindquist
parents:
18
diff
changeset
|
589 assert(_type); |
1 | 590 |
591 llvm::Constant* _init = 0; | |
592 bool _signed = !type->isunsigned(); | |
593 | |
21
8d45266bbabe
[svn r25] * Fixed a lot of problems with string literals
lindquist
parents:
18
diff
changeset
|
594 Logger::println("Creating global variable"); |
8d45266bbabe
[svn r25] * Fixed a lot of problems with string literals
lindquist
parents:
18
diff
changeset
|
595 std::string _name(mangle()); |
52 | 596 |
21
8d45266bbabe
[svn r25] * Fixed a lot of problems with string literals
lindquist
parents:
18
diff
changeset
|
597 llvm::GlobalVariable* gvar = new llvm::GlobalVariable(_type,_isconst,_linkage,0,_name,M); |
8d45266bbabe
[svn r25] * Fixed a lot of problems with string literals
lindquist
parents:
18
diff
changeset
|
598 llvmValue = gvar; |
40 | 599 |
52 | 600 // if extern don't emit initializer |
601 if (!(storage_class & STCextern)) | |
602 { | |
81
3587401b6eeb
[svn r85] Fixed: if a return statement appeared in the try block of a nested try-finally, only the inner-most finally block would be executed.
lindquist
parents:
77
diff
changeset
|
603 _init = DtoConstInitializer(t, init); |
21
8d45266bbabe
[svn r25] * Fixed a lot of problems with string literals
lindquist
parents:
18
diff
changeset
|
604 |
52 | 605 //Logger::cout() << "initializer: " << *_init << '\n'; |
606 if (_type != _init->getType()) { | |
607 Logger::cout() << "got type '" << *_init->getType() << "' expected '" << *_type << "'\n"; | |
608 // zero initalizer | |
609 if (_init->isNullValue()) | |
610 _init = llvm::Constant::getNullValue(_type); | |
611 // pointer to global constant (struct.init) | |
612 else if (llvm::isa<llvm::GlobalVariable>(_init)) | |
613 { | |
614 assert(_init->getType()->getContainedType(0) == _type); | |
615 llvm::GlobalVariable* gv = llvm::cast<llvm::GlobalVariable>(_init); | |
616 assert(t->ty == Tstruct); | |
617 TypeStruct* ts = (TypeStruct*)t; | |
618 assert(ts->sym->llvmInitZ); | |
619 _init = ts->sym->llvmInitZ; | |
620 } | |
621 // array single value init | |
622 else if (llvm::isa<llvm::ArrayType>(_type)) | |
623 { | |
81
3587401b6eeb
[svn r85] Fixed: if a return statement appeared in the try block of a nested try-finally, only the inner-most finally block would be executed.
lindquist
parents:
77
diff
changeset
|
624 _init = DtoConstStaticArray(_type, _init); |
52 | 625 } |
626 else { | |
627 Logger::cout() << "Unexpected initializer type: " << *_type << '\n'; | |
628 //assert(0); | |
629 } | |
1 | 630 } |
52 | 631 |
64
b688ad419f8c
[svn r68] Added support for multi-dimensional static arrays.
lindquist
parents:
63
diff
changeset
|
632 Logger::cout() << "final init = " << *_init << '\n'; |
52 | 633 gvar->setInitializer(_init); |
1 | 634 } |
635 | |
40 | 636 llvmDModule = gIR->dmodule; |
1 | 637 |
638 //if (storage_class & STCprivate) | |
639 // gvar->setVisibility(llvm::GlobalValue::ProtectedVisibility); | |
640 } | |
641 | |
642 // inside aggregate declaration. declare a field. | |
643 else | |
644 { | |
645 Logger::println("Aggregate var declaration: '%s' offset=%d", toChars(), offset); | |
646 | |
81
3587401b6eeb
[svn r85] Fixed: if a return statement appeared in the try block of a nested try-finally, only the inner-most finally block would be executed.
lindquist
parents:
77
diff
changeset
|
647 Type* t = DtoDType(type); |
3587401b6eeb
[svn r85] Fixed: if a return statement appeared in the try block of a nested try-finally, only the inner-most finally block would be executed.
lindquist
parents:
77
diff
changeset
|
648 const llvm::Type* _type = DtoType(t); |
1 | 649 |
81
3587401b6eeb
[svn r85] Fixed: if a return statement appeared in the try block of a nested try-finally, only the inner-most finally block would be executed.
lindquist
parents:
77
diff
changeset
|
650 llvm::Constant*_init = DtoConstInitializer(t, init); |
28
1c80c18f3c82
[svn r32] * Fixed problems with arrays members of aggregates
lindquist
parents:
26
diff
changeset
|
651 assert(_init); |
1c80c18f3c82
[svn r32] * Fixed problems with arrays members of aggregates
lindquist
parents:
26
diff
changeset
|
652 Logger::cout() << "field init is: " << *_init << " type should be " << *_type << '\n'; |
40 | 653 if (_type != _init->getType()) |
1 | 654 { |
40 | 655 if (t->ty == Tsarray) |
1 | 656 { |
657 const llvm::ArrayType* arrty = llvm::cast<llvm::ArrayType>(_type); | |
658 uint64_t n = arrty->getNumElements(); | |
659 std::vector<llvm::Constant*> vals(n,_init); | |
660 _init = llvm::ConstantArray::get(arrty, vals); | |
661 } | |
40 | 662 else if (t->ty == Tarray) |
28
1c80c18f3c82
[svn r32] * Fixed problems with arrays members of aggregates
lindquist
parents:
26
diff
changeset
|
663 { |
1c80c18f3c82
[svn r32] * Fixed problems with arrays members of aggregates
lindquist
parents:
26
diff
changeset
|
664 assert(llvm::isa<llvm::StructType>(_type)); |
1c80c18f3c82
[svn r32] * Fixed problems with arrays members of aggregates
lindquist
parents:
26
diff
changeset
|
665 _init = llvm::ConstantAggregateZero::get(_type); |
1c80c18f3c82
[svn r32] * Fixed problems with arrays members of aggregates
lindquist
parents:
26
diff
changeset
|
666 } |
40 | 667 else if (t->ty == Tstruct) |
28
1c80c18f3c82
[svn r32] * Fixed problems with arrays members of aggregates
lindquist
parents:
26
diff
changeset
|
668 { |
6 | 669 const llvm::StructType* structty = llvm::cast<llvm::StructType>(_type); |
40 | 670 TypeStruct* ts = (TypeStruct*)t; |
9 | 671 assert(ts); |
672 assert(ts->sym); | |
6 | 673 assert(ts->sym->llvmInitZ); |
674 _init = ts->sym->llvmInitZ; | |
675 } | |
40 | 676 else if (t->ty == Tclass) |
28
1c80c18f3c82
[svn r32] * Fixed problems with arrays members of aggregates
lindquist
parents:
26
diff
changeset
|
677 { |
1c80c18f3c82
[svn r32] * Fixed problems with arrays members of aggregates
lindquist
parents:
26
diff
changeset
|
678 _init = llvm::Constant::getNullValue(_type); |
1c80c18f3c82
[svn r32] * Fixed problems with arrays members of aggregates
lindquist
parents:
26
diff
changeset
|
679 } |
1c80c18f3c82
[svn r32] * Fixed problems with arrays members of aggregates
lindquist
parents:
26
diff
changeset
|
680 else { |
1c80c18f3c82
[svn r32] * Fixed problems with arrays members of aggregates
lindquist
parents:
26
diff
changeset
|
681 Logger::println("failed for type %s", type->toChars()); |
1c80c18f3c82
[svn r32] * Fixed problems with arrays members of aggregates
lindquist
parents:
26
diff
changeset
|
682 assert(0); |
1c80c18f3c82
[svn r32] * Fixed problems with arrays members of aggregates
lindquist
parents:
26
diff
changeset
|
683 } |
1 | 684 } |
73 | 685 |
686 // add the field in the IRStruct | |
687 gIR->topstruct().offsets.insert(std::make_pair(offset, IRStruct::Offset(this,_init))); | |
1 | 688 } |
689 | |
690 Logger::println("VarDeclaration::toObjFile is done"); | |
691 } | |
692 | |
693 /* ================================================================== */ | |
694 | |
695 void TypedefDeclaration::toObjFile() | |
696 { | |
697 static int tdi = 0; | |
698 Logger::print("TypedefDeclaration::toObjFile(%d): %s\n", tdi++, toChars()); | |
699 LOG_SCOPE; | |
700 | |
52 | 701 // generate typeinfo |
72 | 702 type->getTypeInfo(NULL); |
1 | 703 } |
704 | |
705 /* ================================================================== */ | |
706 | |
707 void EnumDeclaration::toObjFile() | |
708 { | |
38
27b2f40bdb58
[svn r42] Disabled the extensive logging by default. Use the -vv flag to get it back.
lindquist
parents:
31
diff
changeset
|
709 Logger::println("Ignoring EnumDeclaration::toObjFile for %s", toChars()); |
1 | 710 } |
711 | |
712 /* ================================================================== */ | |
713 | |
714 void FuncDeclaration::toObjFile() | |
715 { | |
18 | 716 if (llvmDModule) { |
9 | 717 assert(llvmValue != 0); |
1 | 718 return; |
719 } | |
720 | |
63
2c39b5292cf3
[svn r67] Fixed ignore unittests instead of failing to compile
lindquist
parents:
58
diff
changeset
|
721 if (isUnitTestDeclaration()) { |
2c39b5292cf3
[svn r67] Fixed ignore unittests instead of failing to compile
lindquist
parents:
58
diff
changeset
|
722 Logger::println("*** ATTENTION: ignoring unittest declaration: %s", toChars()); |
2c39b5292cf3
[svn r67] Fixed ignore unittests instead of failing to compile
lindquist
parents:
58
diff
changeset
|
723 return; |
2c39b5292cf3
[svn r67] Fixed ignore unittests instead of failing to compile
lindquist
parents:
58
diff
changeset
|
724 } |
2c39b5292cf3
[svn r67] Fixed ignore unittests instead of failing to compile
lindquist
parents:
58
diff
changeset
|
725 |
81
3587401b6eeb
[svn r85] Fixed: if a return statement appeared in the try block of a nested try-finally, only the inner-most finally block would be executed.
lindquist
parents:
77
diff
changeset
|
726 Type* t = DtoDType(type); |
55
0ccfae271c45
[svn r59] Added support for C-style variadic functions. Currently only works on x86, x86-64 va_arg is broken in LLVM 2.1. PPC and PPC64 unknown.
lindquist
parents:
54
diff
changeset
|
727 TypeFunction* f = (TypeFunction*)t; |
0ccfae271c45
[svn r59] Added support for C-style variadic functions. Currently only works on x86, x86-64 va_arg is broken in LLVM 2.1. PPC and PPC64 unknown.
lindquist
parents:
54
diff
changeset
|
728 |
0ccfae271c45
[svn r59] Added support for C-style variadic functions. Currently only works on x86, x86-64 va_arg is broken in LLVM 2.1. PPC and PPC64 unknown.
lindquist
parents:
54
diff
changeset
|
729 bool declareOnly = false; |
0ccfae271c45
[svn r59] Added support for C-style variadic functions. Currently only works on x86, x86-64 va_arg is broken in LLVM 2.1. PPC and PPC64 unknown.
lindquist
parents:
54
diff
changeset
|
730 if (TemplateInstance* tinst = parent->isTemplateInstance()) { |
0ccfae271c45
[svn r59] Added support for C-style variadic functions. Currently only works on x86, x86-64 va_arg is broken in LLVM 2.1. PPC and PPC64 unknown.
lindquist
parents:
54
diff
changeset
|
731 TemplateDeclaration* tempdecl = tinst->tempdecl; |
0ccfae271c45
[svn r59] Added support for C-style variadic functions. Currently only works on x86, x86-64 va_arg is broken in LLVM 2.1. PPC and PPC64 unknown.
lindquist
parents:
54
diff
changeset
|
732 if (tempdecl->llvmInternal == LLVMva_start) |
0ccfae271c45
[svn r59] Added support for C-style variadic functions. Currently only works on x86, x86-64 va_arg is broken in LLVM 2.1. PPC and PPC64 unknown.
lindquist
parents:
54
diff
changeset
|
733 { |
0ccfae271c45
[svn r59] Added support for C-style variadic functions. Currently only works on x86, x86-64 va_arg is broken in LLVM 2.1. PPC and PPC64 unknown.
lindquist
parents:
54
diff
changeset
|
734 Logger::println("magic va_start found"); |
0ccfae271c45
[svn r59] Added support for C-style variadic functions. Currently only works on x86, x86-64 va_arg is broken in LLVM 2.1. PPC and PPC64 unknown.
lindquist
parents:
54
diff
changeset
|
735 llvmInternal = LLVMva_start; |
0ccfae271c45
[svn r59] Added support for C-style variadic functions. Currently only works on x86, x86-64 va_arg is broken in LLVM 2.1. PPC and PPC64 unknown.
lindquist
parents:
54
diff
changeset
|
736 declareOnly = true; |
0ccfae271c45
[svn r59] Added support for C-style variadic functions. Currently only works on x86, x86-64 va_arg is broken in LLVM 2.1. PPC and PPC64 unknown.
lindquist
parents:
54
diff
changeset
|
737 } |
0ccfae271c45
[svn r59] Added support for C-style variadic functions. Currently only works on x86, x86-64 va_arg is broken in LLVM 2.1. PPC and PPC64 unknown.
lindquist
parents:
54
diff
changeset
|
738 else if (tempdecl->llvmInternal == LLVMva_arg) |
0ccfae271c45
[svn r59] Added support for C-style variadic functions. Currently only works on x86, x86-64 va_arg is broken in LLVM 2.1. PPC and PPC64 unknown.
lindquist
parents:
54
diff
changeset
|
739 { |
0ccfae271c45
[svn r59] Added support for C-style variadic functions. Currently only works on x86, x86-64 va_arg is broken in LLVM 2.1. PPC and PPC64 unknown.
lindquist
parents:
54
diff
changeset
|
740 Logger::println("magic va_arg found"); |
0ccfae271c45
[svn r59] Added support for C-style variadic functions. Currently only works on x86, x86-64 va_arg is broken in LLVM 2.1. PPC and PPC64 unknown.
lindquist
parents:
54
diff
changeset
|
741 llvmInternal = LLVMva_arg; |
0ccfae271c45
[svn r59] Added support for C-style variadic functions. Currently only works on x86, x86-64 va_arg is broken in LLVM 2.1. PPC and PPC64 unknown.
lindquist
parents:
54
diff
changeset
|
742 return; |
0ccfae271c45
[svn r59] Added support for C-style variadic functions. Currently only works on x86, x86-64 va_arg is broken in LLVM 2.1. PPC and PPC64 unknown.
lindquist
parents:
54
diff
changeset
|
743 } |
0ccfae271c45
[svn r59] Added support for C-style variadic functions. Currently only works on x86, x86-64 va_arg is broken in LLVM 2.1. PPC and PPC64 unknown.
lindquist
parents:
54
diff
changeset
|
744 } |
0ccfae271c45
[svn r59] Added support for C-style variadic functions. Currently only works on x86, x86-64 va_arg is broken in LLVM 2.1. PPC and PPC64 unknown.
lindquist
parents:
54
diff
changeset
|
745 |
81
3587401b6eeb
[svn r85] Fixed: if a return statement appeared in the try block of a nested try-finally, only the inner-most finally block would be executed.
lindquist
parents:
77
diff
changeset
|
746 llvm::Function* func = DtoDeclareFunction(this); |
9 | 747 |
55
0ccfae271c45
[svn r59] Added support for C-style variadic functions. Currently only works on x86, x86-64 va_arg is broken in LLVM 2.1. PPC and PPC64 unknown.
lindquist
parents:
54
diff
changeset
|
748 if (declareOnly) |
0ccfae271c45
[svn r59] Added support for C-style variadic functions. Currently only works on x86, x86-64 va_arg is broken in LLVM 2.1. PPC and PPC64 unknown.
lindquist
parents:
54
diff
changeset
|
749 return; |
0ccfae271c45
[svn r59] Added support for C-style variadic functions. Currently only works on x86, x86-64 va_arg is broken in LLVM 2.1. PPC and PPC64 unknown.
lindquist
parents:
54
diff
changeset
|
750 |
31
2841234d2aea
[svn r35] * Attributes on struct fields/methods now work
lindquist
parents:
28
diff
changeset
|
751 if (!gIR->structs.empty() && gIR->topstruct().queueFuncs) { |
11
d3ee9efe20e2
[svn r15] * Fixed a bunch problems with virtual calls. Seems I did some rather poor testing.
lindquist
parents:
10
diff
changeset
|
752 if (!llvmQueued) { |
d3ee9efe20e2
[svn r15] * Fixed a bunch problems with virtual calls. Seems I did some rather poor testing.
lindquist
parents:
10
diff
changeset
|
753 Logger::println("queueing %s", toChars()); |
31
2841234d2aea
[svn r35] * Attributes on struct fields/methods now work
lindquist
parents:
28
diff
changeset
|
754 gIR->topstruct().funcs.push_back(this); |
11
d3ee9efe20e2
[svn r15] * Fixed a bunch problems with virtual calls. Seems I did some rather poor testing.
lindquist
parents:
10
diff
changeset
|
755 llvmQueued = true; |
d3ee9efe20e2
[svn r15] * Fixed a bunch problems with virtual calls. Seems I did some rather poor testing.
lindquist
parents:
10
diff
changeset
|
756 } |
10 | 757 return; // we wait with the definition as they might invoke a virtual method and the vtable is not yet complete |
1 | 758 } |
759 | |
82
d8dd47ef3973
[svn r86] Changed the way arguments are given storage. It is now detected if they will need it during semantic passes.
lindquist
parents:
81
diff
changeset
|
760 // debug info |
d8dd47ef3973
[svn r86] Changed the way arguments are given storage. It is now detected if they will need it during semantic passes.
lindquist
parents:
81
diff
changeset
|
761 if (global.params.symdebug) { |
d8dd47ef3973
[svn r86] Changed the way arguments are given storage. It is now detected if they will need it during semantic passes.
lindquist
parents:
81
diff
changeset
|
762 llvmDwarfSubProgram = DtoDwarfSubProgram(this); |
d8dd47ef3973
[svn r86] Changed the way arguments are given storage. It is now detected if they will need it during semantic passes.
lindquist
parents:
81
diff
changeset
|
763 } |
d8dd47ef3973
[svn r86] Changed the way arguments are given storage. It is now detected if they will need it during semantic passes.
lindquist
parents:
81
diff
changeset
|
764 |
11
d3ee9efe20e2
[svn r15] * Fixed a bunch problems with virtual calls. Seems I did some rather poor testing.
lindquist
parents:
10
diff
changeset
|
765 assert(f->llvmType); |
d3ee9efe20e2
[svn r15] * Fixed a bunch problems with virtual calls. Seems I did some rather poor testing.
lindquist
parents:
10
diff
changeset
|
766 const llvm::FunctionType* functype = llvm::cast<llvm::FunctionType>(llvmValue->getType()->getContainedType(0)); |
1 | 767 |
768 // only members of the current module maybe be defined | |
17
6c6cd097bcdf
[svn r21] * Fixed local instances of imported templates
lindquist
parents:
15
diff
changeset
|
769 if (getModule() == gIR->dmodule || parent->isTemplateInstance()) |
1 | 770 { |
11
d3ee9efe20e2
[svn r15] * Fixed a bunch problems with virtual calls. Seems I did some rather poor testing.
lindquist
parents:
10
diff
changeset
|
771 llvmDModule = gIR->dmodule; |
d3ee9efe20e2
[svn r15] * Fixed a bunch problems with virtual calls. Seems I did some rather poor testing.
lindquist
parents:
10
diff
changeset
|
772 |
1 | 773 // handle static constructor / destructor |
774 if (isStaticCtorDeclaration() || isStaticDtorDeclaration()) { | |
775 const llvm::ArrayType* sctor_type = llvm::ArrayType::get(llvm::PointerType::get(functype),1); | |
776 //Logger::cout() << "static ctor type: " << *sctor_type << '\n'; | |
11
d3ee9efe20e2
[svn r15] * Fixed a bunch problems with virtual calls. Seems I did some rather poor testing.
lindquist
parents:
10
diff
changeset
|
777 |
1 | 778 llvm::Constant* sctor_func = llvm::cast<llvm::Constant>(llvmValue); |
779 //Logger::cout() << "static ctor func: " << *sctor_func << '\n'; | |
11
d3ee9efe20e2
[svn r15] * Fixed a bunch problems with virtual calls. Seems I did some rather poor testing.
lindquist
parents:
10
diff
changeset
|
780 |
74 | 781 llvm::Constant* sctor_init = llvm::ConstantArray::get(sctor_type,&sctor_func,1); |
11
d3ee9efe20e2
[svn r15] * Fixed a bunch problems with virtual calls. Seems I did some rather poor testing.
lindquist
parents:
10
diff
changeset
|
782 |
1 | 783 //Logger::cout() << "static ctor init: " << *sctor_init << '\n'; |
11
d3ee9efe20e2
[svn r15] * Fixed a bunch problems with virtual calls. Seems I did some rather poor testing.
lindquist
parents:
10
diff
changeset
|
784 |
1 | 785 // output the llvm.global_ctors array |
786 const char* varname = isStaticCtorDeclaration() ? "_d_module_ctor_array" : "_d_module_dtor_array"; | |
787 llvm::GlobalVariable* sctor_arr = new llvm::GlobalVariable(sctor_type, false, llvm::GlobalValue::AppendingLinkage, sctor_init, varname, gIR->module); | |
788 } | |
789 | |
790 // function definition | |
74 | 791 if (fbody != 0) |
1 | 792 { |
40 | 793 gIR->functions.push_back(IRFunction(this)); |
794 gIR->func().func = func; | |
15
37a4fdab33fc
[svn r19] * Added support for reassigning 'this' inside class constructors.
lindquist
parents:
14
diff
changeset
|
795 |
11
d3ee9efe20e2
[svn r15] * Fixed a bunch problems with virtual calls. Seems I did some rather poor testing.
lindquist
parents:
10
diff
changeset
|
796 // first make absolutely sure the type is up to date |
d3ee9efe20e2
[svn r15] * Fixed a bunch problems with virtual calls. Seems I did some rather poor testing.
lindquist
parents:
10
diff
changeset
|
797 f->llvmType = llvmValue->getType()->getContainedType(0); |
d3ee9efe20e2
[svn r15] * Fixed a bunch problems with virtual calls. Seems I did some rather poor testing.
lindquist
parents:
10
diff
changeset
|
798 |
52 | 799 //Logger::cout() << "func type: " << *f->llvmType << '\n'; |
31
2841234d2aea
[svn r35] * Attributes on struct fields/methods now work
lindquist
parents:
28
diff
changeset
|
800 |
15
37a4fdab33fc
[svn r19] * Added support for reassigning 'this' inside class constructors.
lindquist
parents:
14
diff
changeset
|
801 // this handling |
37a4fdab33fc
[svn r19] * Added support for reassigning 'this' inside class constructors.
lindquist
parents:
14
diff
changeset
|
802 if (f->llvmUsesThis) { |
50
6fcc08a4d406
[svn r54] Added support for nested delegates referencing parent's stack variables.
lindquist
parents:
40
diff
changeset
|
803 Logger::println("uses this"); |
15
37a4fdab33fc
[svn r19] * Added support for reassigning 'this' inside class constructors.
lindquist
parents:
14
diff
changeset
|
804 if (f->llvmRetInPtr) |
37a4fdab33fc
[svn r19] * Added support for reassigning 'this' inside class constructors.
lindquist
parents:
14
diff
changeset
|
805 llvmThisVar = ++func->arg_begin(); |
37a4fdab33fc
[svn r19] * Added support for reassigning 'this' inside class constructors.
lindquist
parents:
14
diff
changeset
|
806 else |
37a4fdab33fc
[svn r19] * Added support for reassigning 'this' inside class constructors.
lindquist
parents:
14
diff
changeset
|
807 llvmThisVar = func->arg_begin(); |
37a4fdab33fc
[svn r19] * Added support for reassigning 'this' inside class constructors.
lindquist
parents:
14
diff
changeset
|
808 assert(llvmThisVar != 0); |
37a4fdab33fc
[svn r19] * Added support for reassigning 'this' inside class constructors.
lindquist
parents:
14
diff
changeset
|
809 } |
37a4fdab33fc
[svn r19] * Added support for reassigning 'this' inside class constructors.
lindquist
parents:
14
diff
changeset
|
810 |
9 | 811 if (isMain()) |
812 gIR->emitMain = true; | |
813 | |
40 | 814 llvm::BasicBlock* beginbb = new llvm::BasicBlock("entry",func); |
815 llvm::BasicBlock* endbb = new llvm::BasicBlock("endentry",func); | |
1 | 816 |
817 //assert(gIR->scopes.empty()); | |
40 | 818 gIR->scopes.push_back(IRScope(beginbb, endbb)); |
11
d3ee9efe20e2
[svn r15] * Fixed a bunch problems with virtual calls. Seems I did some rather poor testing.
lindquist
parents:
10
diff
changeset
|
819 |
1 | 820 // create alloca point |
821 f->llvmAllocaPoint = new llvm::BitCastInst(llvm::ConstantInt::get(llvm::Type::Int32Ty,0,false),llvm::Type::Int32Ty,"alloca point",gIR->scopebb()); | |
40 | 822 gIR->func().allocapoint = f->llvmAllocaPoint; |
11
d3ee9efe20e2
[svn r15] * Fixed a bunch problems with virtual calls. Seems I did some rather poor testing.
lindquist
parents:
10
diff
changeset
|
823 |
82
d8dd47ef3973
[svn r86] Changed the way arguments are given storage. It is now detected if they will need it during semantic passes.
lindquist
parents:
81
diff
changeset
|
824 // give arguments storage |
d8dd47ef3973
[svn r86] Changed the way arguments are given storage. It is now detected if they will need it during semantic passes.
lindquist
parents:
81
diff
changeset
|
825 size_t n = Argument::dim(f->parameters); |
d8dd47ef3973
[svn r86] Changed the way arguments are given storage. It is now detected if they will need it during semantic passes.
lindquist
parents:
81
diff
changeset
|
826 for (int i=0; i < n; ++i) { |
d8dd47ef3973
[svn r86] Changed the way arguments are given storage. It is now detected if they will need it during semantic passes.
lindquist
parents:
81
diff
changeset
|
827 Argument* arg = Argument::getNth(f->parameters, i); |
d8dd47ef3973
[svn r86] Changed the way arguments are given storage. It is now detected if they will need it during semantic passes.
lindquist
parents:
81
diff
changeset
|
828 if (arg && arg->vardecl) { |
d8dd47ef3973
[svn r86] Changed the way arguments are given storage. It is now detected if they will need it during semantic passes.
lindquist
parents:
81
diff
changeset
|
829 VarDeclaration* vd = arg->vardecl; |
d8dd47ef3973
[svn r86] Changed the way arguments are given storage. It is now detected if they will need it during semantic passes.
lindquist
parents:
81
diff
changeset
|
830 if (!vd->llvmNeedsStorage || vd->nestedref || vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type)) |
d8dd47ef3973
[svn r86] Changed the way arguments are given storage. It is now detected if they will need it during semantic passes.
lindquist
parents:
81
diff
changeset
|
831 continue; |
d8dd47ef3973
[svn r86] Changed the way arguments are given storage. It is now detected if they will need it during semantic passes.
lindquist
parents:
81
diff
changeset
|
832 llvm::Value* a = vd->llvmValue; |
d8dd47ef3973
[svn r86] Changed the way arguments are given storage. It is now detected if they will need it during semantic passes.
lindquist
parents:
81
diff
changeset
|
833 assert(a); |
d8dd47ef3973
[svn r86] Changed the way arguments are given storage. It is now detected if they will need it during semantic passes.
lindquist
parents:
81
diff
changeset
|
834 std::string s(a->getName()); |
d8dd47ef3973
[svn r86] Changed the way arguments are given storage. It is now detected if they will need it during semantic passes.
lindquist
parents:
81
diff
changeset
|
835 Logger::println("giving argument '%s' storage", s.c_str()); |
d8dd47ef3973
[svn r86] Changed the way arguments are given storage. It is now detected if they will need it during semantic passes.
lindquist
parents:
81
diff
changeset
|
836 s.append("_storage"); |
d8dd47ef3973
[svn r86] Changed the way arguments are given storage. It is now detected if they will need it during semantic passes.
lindquist
parents:
81
diff
changeset
|
837 llvm::Value* v = new llvm::AllocaInst(a->getType(),s,f->llvmAllocaPoint); |
d8dd47ef3973
[svn r86] Changed the way arguments are given storage. It is now detected if they will need it during semantic passes.
lindquist
parents:
81
diff
changeset
|
838 gIR->ir->CreateStore(a,v); |
d8dd47ef3973
[svn r86] Changed the way arguments are given storage. It is now detected if they will need it during semantic passes.
lindquist
parents:
81
diff
changeset
|
839 vd->llvmValue = v; |
d8dd47ef3973
[svn r86] Changed the way arguments are given storage. It is now detected if they will need it during semantic passes.
lindquist
parents:
81
diff
changeset
|
840 } |
d8dd47ef3973
[svn r86] Changed the way arguments are given storage. It is now detected if they will need it during semantic passes.
lindquist
parents:
81
diff
changeset
|
841 else assert(0); |
d8dd47ef3973
[svn r86] Changed the way arguments are given storage. It is now detected if they will need it during semantic passes.
lindquist
parents:
81
diff
changeset
|
842 } |
d8dd47ef3973
[svn r86] Changed the way arguments are given storage. It is now detected if they will need it during semantic passes.
lindquist
parents:
81
diff
changeset
|
843 |
d8dd47ef3973
[svn r86] Changed the way arguments are given storage. It is now detected if they will need it during semantic passes.
lindquist
parents:
81
diff
changeset
|
844 // debug info |
d8dd47ef3973
[svn r86] Changed the way arguments are given storage. It is now detected if they will need it during semantic passes.
lindquist
parents:
81
diff
changeset
|
845 if (global.params.symdebug) DtoDwarfFuncStart(this); |
d8dd47ef3973
[svn r86] Changed the way arguments are given storage. It is now detected if they will need it during semantic passes.
lindquist
parents:
81
diff
changeset
|
846 |
50
6fcc08a4d406
[svn r54] Added support for nested delegates referencing parent's stack variables.
lindquist
parents:
40
diff
changeset
|
847 llvm::Value* parentNested = NULL; |
6fcc08a4d406
[svn r54] Added support for nested delegates referencing parent's stack variables.
lindquist
parents:
40
diff
changeset
|
848 if (FuncDeclaration* fd = toParent()->isFuncDeclaration()) { |
6fcc08a4d406
[svn r54] Added support for nested delegates referencing parent's stack variables.
lindquist
parents:
40
diff
changeset
|
849 parentNested = fd->llvmNested; |
6fcc08a4d406
[svn r54] Added support for nested delegates referencing parent's stack variables.
lindquist
parents:
40
diff
changeset
|
850 } |
6fcc08a4d406
[svn r54] Added support for nested delegates referencing parent's stack variables.
lindquist
parents:
40
diff
changeset
|
851 |
6fcc08a4d406
[svn r54] Added support for nested delegates referencing parent's stack variables.
lindquist
parents:
40
diff
changeset
|
852 // construct nested variables struct |
6fcc08a4d406
[svn r54] Added support for nested delegates referencing parent's stack variables.
lindquist
parents:
40
diff
changeset
|
853 if (!llvmNestedVars.empty() || parentNested) { |
6fcc08a4d406
[svn r54] Added support for nested delegates referencing parent's stack variables.
lindquist
parents:
40
diff
changeset
|
854 std::vector<const llvm::Type*> nestTypes; |
6fcc08a4d406
[svn r54] Added support for nested delegates referencing parent's stack variables.
lindquist
parents:
40
diff
changeset
|
855 int j = 0; |
6fcc08a4d406
[svn r54] Added support for nested delegates referencing parent's stack variables.
lindquist
parents:
40
diff
changeset
|
856 if (parentNested) { |
6fcc08a4d406
[svn r54] Added support for nested delegates referencing parent's stack variables.
lindquist
parents:
40
diff
changeset
|
857 nestTypes.push_back(parentNested->getType()); |
6fcc08a4d406
[svn r54] Added support for nested delegates referencing parent's stack variables.
lindquist
parents:
40
diff
changeset
|
858 j++; |
6fcc08a4d406
[svn r54] Added support for nested delegates referencing parent's stack variables.
lindquist
parents:
40
diff
changeset
|
859 } |
6fcc08a4d406
[svn r54] Added support for nested delegates referencing parent's stack variables.
lindquist
parents:
40
diff
changeset
|
860 for (std::set<VarDeclaration*>::iterator i=llvmNestedVars.begin(); i!=llvmNestedVars.end(); ++i) { |
6fcc08a4d406
[svn r54] Added support for nested delegates referencing parent's stack variables.
lindquist
parents:
40
diff
changeset
|
861 VarDeclaration* vd = *i; |
6fcc08a4d406
[svn r54] Added support for nested delegates referencing parent's stack variables.
lindquist
parents:
40
diff
changeset
|
862 vd->llvmNestedIndex = j++; |
67
f918f3e2e99e
[svn r71] Fixed accessing parent function arguments from inside nested delegates.
lindquist
parents:
64
diff
changeset
|
863 if (vd->isParameter()) { |
f918f3e2e99e
[svn r71] Fixed accessing parent function arguments from inside nested delegates.
lindquist
parents:
64
diff
changeset
|
864 assert(vd->llvmValue); |
f918f3e2e99e
[svn r71] Fixed accessing parent function arguments from inside nested delegates.
lindquist
parents:
64
diff
changeset
|
865 nestTypes.push_back(vd->llvmValue->getType()); |
f918f3e2e99e
[svn r71] Fixed accessing parent function arguments from inside nested delegates.
lindquist
parents:
64
diff
changeset
|
866 } |
f918f3e2e99e
[svn r71] Fixed accessing parent function arguments from inside nested delegates.
lindquist
parents:
64
diff
changeset
|
867 else { |
81
3587401b6eeb
[svn r85] Fixed: if a return statement appeared in the try block of a nested try-finally, only the inner-most finally block would be executed.
lindquist
parents:
77
diff
changeset
|
868 nestTypes.push_back(DtoType(vd->type)); |
67
f918f3e2e99e
[svn r71] Fixed accessing parent function arguments from inside nested delegates.
lindquist
parents:
64
diff
changeset
|
869 } |
50
6fcc08a4d406
[svn r54] Added support for nested delegates referencing parent's stack variables.
lindquist
parents:
40
diff
changeset
|
870 } |
6fcc08a4d406
[svn r54] Added support for nested delegates referencing parent's stack variables.
lindquist
parents:
40
diff
changeset
|
871 const llvm::StructType* nestSType = llvm::StructType::get(nestTypes); |
6fcc08a4d406
[svn r54] Added support for nested delegates referencing parent's stack variables.
lindquist
parents:
40
diff
changeset
|
872 Logger::cout() << "nested var struct has type:" << '\n' << *nestSType; |
6fcc08a4d406
[svn r54] Added support for nested delegates referencing parent's stack variables.
lindquist
parents:
40
diff
changeset
|
873 llvmNested = new llvm::AllocaInst(nestSType,"nestedvars",f->llvmAllocaPoint); |
6fcc08a4d406
[svn r54] Added support for nested delegates referencing parent's stack variables.
lindquist
parents:
40
diff
changeset
|
874 if (parentNested) { |
6fcc08a4d406
[svn r54] Added support for nested delegates referencing parent's stack variables.
lindquist
parents:
40
diff
changeset
|
875 assert(llvmThisVar); |
6fcc08a4d406
[svn r54] Added support for nested delegates referencing parent's stack variables.
lindquist
parents:
40
diff
changeset
|
876 llvm::Value* ptr = gIR->ir->CreateBitCast(llvmThisVar, parentNested->getType(), "tmp"); |
81
3587401b6eeb
[svn r85] Fixed: if a return statement appeared in the try block of a nested try-finally, only the inner-most finally block would be executed.
lindquist
parents:
77
diff
changeset
|
877 gIR->ir->CreateStore(ptr, DtoGEPi(llvmNested, 0,0, "tmp")); |
50
6fcc08a4d406
[svn r54] Added support for nested delegates referencing parent's stack variables.
lindquist
parents:
40
diff
changeset
|
878 } |
67
f918f3e2e99e
[svn r71] Fixed accessing parent function arguments from inside nested delegates.
lindquist
parents:
64
diff
changeset
|
879 for (std::set<VarDeclaration*>::iterator i=llvmNestedVars.begin(); i!=llvmNestedVars.end(); ++i) { |
f918f3e2e99e
[svn r71] Fixed accessing parent function arguments from inside nested delegates.
lindquist
parents:
64
diff
changeset
|
880 VarDeclaration* vd = *i; |
f918f3e2e99e
[svn r71] Fixed accessing parent function arguments from inside nested delegates.
lindquist
parents:
64
diff
changeset
|
881 if (vd->isParameter()) { |
81
3587401b6eeb
[svn r85] Fixed: if a return statement appeared in the try block of a nested try-finally, only the inner-most finally block would be executed.
lindquist
parents:
77
diff
changeset
|
882 gIR->ir->CreateStore(vd->llvmValue, DtoGEPi(llvmNested, 0, vd->llvmNestedIndex, "tmp")); |
68
c4b3f5d2cd9b
[svn r72] Calling a nested function that is not a delegate was not working.
lindquist
parents:
67
diff
changeset
|
883 vd->llvmValue = llvmNested; |
67
f918f3e2e99e
[svn r71] Fixed accessing parent function arguments from inside nested delegates.
lindquist
parents:
64
diff
changeset
|
884 } |
f918f3e2e99e
[svn r71] Fixed accessing parent function arguments from inside nested delegates.
lindquist
parents:
64
diff
changeset
|
885 } |
50
6fcc08a4d406
[svn r54] Added support for nested delegates referencing parent's stack variables.
lindquist
parents:
40
diff
changeset
|
886 } |
6fcc08a4d406
[svn r54] Added support for nested delegates referencing parent's stack variables.
lindquist
parents:
40
diff
changeset
|
887 |
57
a9d29e9f1fed
[svn r61] Added support for D-style variadic functions :)
lindquist
parents:
55
diff
changeset
|
888 // copy _argptr to a memory location |
a9d29e9f1fed
[svn r61] Added support for D-style variadic functions :)
lindquist
parents:
55
diff
changeset
|
889 if (f->linkage == LINKd && f->varargs == 1) |
a9d29e9f1fed
[svn r61] Added support for D-style variadic functions :)
lindquist
parents:
55
diff
changeset
|
890 { |
a9d29e9f1fed
[svn r61] Added support for D-style variadic functions :)
lindquist
parents:
55
diff
changeset
|
891 llvm::Value* argptrmem = new llvm::AllocaInst(llvmArgPtr->getType(), "_argptrmem", gIR->topallocapoint()); |
a9d29e9f1fed
[svn r61] Added support for D-style variadic functions :)
lindquist
parents:
55
diff
changeset
|
892 new llvm::StoreInst(llvmArgPtr, argptrmem, gIR->scopebb()); |
a9d29e9f1fed
[svn r61] Added support for D-style variadic functions :)
lindquist
parents:
55
diff
changeset
|
893 llvmArgPtr = argptrmem; |
a9d29e9f1fed
[svn r61] Added support for D-style variadic functions :)
lindquist
parents:
55
diff
changeset
|
894 } |
a9d29e9f1fed
[svn r61] Added support for D-style variadic functions :)
lindquist
parents:
55
diff
changeset
|
895 |
1 | 896 // output function body |
897 fbody->toIR(gIR); | |
898 | |
899 // llvm requires all basic blocks to end with a TerminatorInst but DMD does not put a return statement | |
900 // in automatically, so we do it here. | |
40 | 901 if (!isMain()) { |
52 | 902 if (!gIR->scopereturned()) { |
40 | 903 // pass the previous block into this block |
82
d8dd47ef3973
[svn r86] Changed the way arguments are given storage. It is now detected if they will need it during semantic passes.
lindquist
parents:
81
diff
changeset
|
904 if (global.params.symdebug) DtoDwarfFuncEnd(this); |
40 | 905 if (func->getReturnType() == llvm::Type::VoidTy) { |
906 new llvm::ReturnInst(gIR->scopebb()); | |
907 } | |
52 | 908 else { |
909 new llvm::ReturnInst(llvm::UndefValue::get(func->getReturnType()), gIR->scopebb()); | |
910 } | |
40 | 911 } |
1 | 912 } |
11
d3ee9efe20e2
[svn r15] * Fixed a bunch problems with virtual calls. Seems I did some rather poor testing.
lindquist
parents:
10
diff
changeset
|
913 |
1 | 914 // erase alloca point |
915 f->llvmAllocaPoint->eraseFromParent(); | |
916 f->llvmAllocaPoint = 0; | |
40 | 917 gIR->func().allocapoint = 0; |
1 | 918 |
919 gIR->scopes.pop_back(); | |
920 | |
921 // get rid of the endentry block, it's never used | |
9 | 922 assert(!func->getBasicBlockList().empty()); |
1 | 923 func->getBasicBlockList().pop_back(); |
924 | |
925 // if the last block is empty now, it must be unreachable or it's a bug somewhere else | |
9 | 926 // would be nice to figure out how to assert that this is correct |
1 | 927 llvm::BasicBlock* lastbb = &func->getBasicBlockList().back(); |
928 if (lastbb->empty()) { | |
52 | 929 if (lastbb->getNumUses() == 0) |
930 lastbb->eraseFromParent(); | |
931 else { | |
932 new llvm::UnreachableInst(lastbb); | |
933 /*if (func->getReturnType() == llvm::Type::VoidTy) { | |
934 new llvm::ReturnInst(lastbb); | |
935 } | |
936 else { | |
937 new llvm::ReturnInst(llvm::UndefValue::get(func->getReturnType()), lastbb); | |
938 }*/ | |
939 } | |
1 | 940 } |
15
37a4fdab33fc
[svn r19] * Added support for reassigning 'this' inside class constructors.
lindquist
parents:
14
diff
changeset
|
941 |
40 | 942 gIR->functions.pop_back(); |
1 | 943 } |
17
6c6cd097bcdf
[svn r21] * Fixed local instances of imported templates
lindquist
parents:
15
diff
changeset
|
944 |
6c6cd097bcdf
[svn r21] * Fixed local instances of imported templates
lindquist
parents:
15
diff
changeset
|
945 // template instances should have weak linkage |
6c6cd097bcdf
[svn r21] * Fixed local instances of imported templates
lindquist
parents:
15
diff
changeset
|
946 if (parent->isTemplateInstance()) { |
6c6cd097bcdf
[svn r21] * Fixed local instances of imported templates
lindquist
parents:
15
diff
changeset
|
947 func->setLinkage(llvm::GlobalValue::WeakLinkage); |
6c6cd097bcdf
[svn r21] * Fixed local instances of imported templates
lindquist
parents:
15
diff
changeset
|
948 } |
1 | 949 } |
950 } |