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