comparison ir/irstruct.cpp @ 797:340acf1535d0

Removed KDevelop3 project files, CMake can generate them just fine! Fixed function literals in static initializers. Changed alignment of delegates from 2*PTRSIZE to just PTRSIZE. Changed errors to go to stderr instead of stdout. Fairly major rewriting of struct/union/class handling, STILL A BIT BUGGY !!!
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Sat, 29 Nov 2008 21:25:43 +0100
parents 041c1596d217
children d14e4594c7d7
comparison
equal deleted inserted replaced
796:6e7a4c3b64d2 797:340acf1535d0
1 #include "gen/llvm.h" 1 #include "gen/llvm.h"
2 2
3 #include "mtype.h" 3 #include "mtype.h"
4 #include "aggregate.h" 4 #include "aggregate.h"
5 #include "declaration.h" 5 #include "declaration.h"
6 #include "init.h"
6 7
7 #include "ir/irstruct.h" 8 #include "ir/irstruct.h"
8 #include "gen/irstate.h" 9 #include "gen/irstate.h"
9 #include "gen/tollvm.h" 10 #include "gen/tollvm.h"
11 #include "gen/logger.h"
10 12
11 IrInterface::IrInterface(BaseClass* b) 13 IrInterface::IrInterface(BaseClass* b)
14 : vtblInitTy(llvm::OpaqueType::get())
12 { 15 {
13 base = b; 16 base = b;
14 decl = b->base; 17 decl = b->base;
15 vtblTy = NULL;
16 vtblInit = NULL; 18 vtblInit = NULL;
17 vtbl = NULL; 19 vtbl = NULL;
18 infoTy = NULL; 20 infoTy = NULL;
19 infoInit = NULL; 21 infoInit = NULL;
20 info = NULL; 22 info = NULL;
21 23
22 index = -1; 24 index = 0;
23 }
24
25 IrInterface::~IrInterface()
26 {
27 delete vtblTy;
28 } 25 }
29 26
30 ////////////////////////////////////////////////////////////////////////////// 27 //////////////////////////////////////////////////////////////////////////////
31 ////////////////////////////////////////////////////////////////////////////// 28 //////////////////////////////////////////////////////////////////////////////
32 ////////////////////////////////////////////////////////////////////////////// 29 //////////////////////////////////////////////////////////////////////////////
33 30
34 IrStruct::IrStruct(Type* t) 31 IrStruct::IrStruct(AggregateDeclaration* aggr)
35 : recty((t->ir.type) ? *t->ir.type : llvm::OpaqueType::get()) 32 : initOpaque(llvm::OpaqueType::get()),
36 { 33 classInfoOpaque(llvm::OpaqueType::get()),
37 type = t; 34 vtblTy(llvm::OpaqueType::get()),
35 vtblInitTy(llvm::OpaqueType::get())
36 {
37 aggrdecl = aggr;
38 defaultFound = false;
39 anon = NULL;
40 index = 0;
41
42 type = aggr->type;
38 defined = false; 43 defined = false;
39 constinited = false; 44 constinited = false;
40 interfaceInfosTy = NULL; 45
41 interfaceInfos = NULL; 46 interfaceInfos = NULL;
42
43 vtbl = NULL; 47 vtbl = NULL;
44 constVtbl = NULL; 48 constVtbl = NULL;
49
45 init = NULL; 50 init = NULL;
46 constInit = NULL; 51 constInit = NULL;
52
47 classInfo = NULL; 53 classInfo = NULL;
48 constClassInfo = NULL; 54 constClassInfo = NULL;
49 hasUnions = false; 55 classInfoDeclared = false;
50 dunion = NULL; 56 classInfoDefined = false;
51
52 classDeclared = false;
53 classDefined = false;
54 57
55 packed = false; 58 packed = false;
56 59
57 dwarfComposite = NULL; 60 dwarfComposite = NULL;
58 } 61 }
59 62
60 IrStruct::~IrStruct() 63 IrStruct::~IrStruct()
61 { 64 {
62 } 65 }
63 66
64 void IrStruct::addField(VarDeclaration* v) 67 //////////////////////////////////////////
65 { 68
66 // might already have its irField, as classes derive each other without getting copies of the VarDeclaration 69 void IrStruct::pushAnon(bool isunion)
67 if (!v->ir.irField) 70 {
68 { 71 anon = new Anon(isunion, anon);
69 assert(!v->ir.isSet()); 72 }
70 v->ir.irField = new IrField(v); 73
71 } 74 //////////////////////////////////////////
72 const LLType* _type = DtoType(v->type); 75
73 offsets.insert(std::make_pair(v->offset, IrStruct::Offset(v, _type))); 76 void IrStruct::popAnon()
74 } 77 {
78 assert(anon);
79
80 const LLType* BT;
81
82 // get the anon type
83 if (anon->isunion)
84 {
85 // get biggest type in block
86 const LLType* biggest = getBiggestType(&anon->types[0], anon->types.size());
87 std::vector<const LLType*> vec(1, biggest);
88 BT = LLStructType::get(vec, aggrdecl->ir.irStruct->packed);
89 }
90 else
91 {
92 // build a struct from the types
93 BT = LLStructType::get(anon->types, aggrdecl->ir.irStruct->packed);
94 }
95
96 // pop anon
97 Anon* tmp = anon;
98 anon = anon->parent;
99 delete tmp;
100
101 // is there a parent anon?
102 if (anon)
103 {
104 // make sure type gets pushed in the anon, not the main
105 anon->types.push_back(BT);
106 // index is only manipulated at the top level, anons use raw offsets
107 }
108 // no parent anon, finally add to aggrdecl
109 else
110 {
111 types.push_back(BT);
112 // only advance to next position if main is not a union
113 if (!aggrdecl->isUnionDeclaration())
114 {
115 index++;
116 }
117 }
118 }
119
120 //////////////////////////////////////////
121
122 void addZeros(std::vector<const llvm::Type*>& inits, size_t pos, size_t offset);
123
124 void IrStruct::addVar(VarDeclaration * var)
125 {
126 TypeVector* tvec = &types;
127 if (anon)
128 {
129 // make sure type gets pushed in the anon, not the main
130 tvec = &anon->types;
131
132 // set but don't advance index
133 var->ir.irField->index = index;
134
135 // set offset in bytes from start of anon block
136 var->ir.irField->unionOffset = var->offset - var->offset2;
137 }
138 else if (aggrdecl->isUnionDeclaration())
139 {
140 // set but don't advance index
141 var->ir.irField->index = index;
142 }
143 else
144 {
145 // set and advance index
146 var->ir.irField->index = index++;
147 }
148
149 // add type
150 tvec->push_back(DtoType(var->type));
151
152 // add var
153 varDecls.push_back(var);
154 }
155
156 //////////////////////////////////////////
157
158 const LLType* IrStruct::build()
159 {
160 // if types is empty, add a byte
161 if (types.empty())
162 {
163 types.push_back(LLType::Int8Ty);
164 }
165
166 // union type
167 if (aggrdecl->isUnionDeclaration())
168 {
169 const LLType* biggest = getBiggestType(&types[0], types.size());
170 std::vector<const LLType*> vec(1, biggest);
171 return LLStructType::get(vec, aggrdecl->ir.irStruct->packed);
172 }
173 // struct/class type
174 else
175 {
176 return LLStructType::get(types, aggrdecl->ir.irStruct->packed);
177 }
178 }
179
180 void addZeros(std::vector<const llvm::Type*>& inits, size_t pos, size_t offset)
181 {
182 assert(offset > pos);
183 size_t diff = offset - pos;
184
185 size_t sz;
186
187 do
188 {
189 if (pos%8 == 0 && diff >= 8)
190 sz = 8;
191 else if (pos%4 == 0 && diff >= 4)
192 sz = 4;
193 else if (pos%2 == 0 && diff >= 2)
194 sz = 2;
195 else // if (pos % 1 == 0)
196 sz = 1;
197 inits.push_back(LLIntegerType::get(sz*8));
198 pos += sz;
199 diff -= sz;
200 } while (pos < offset);
201
202 assert(pos == offset);
203 }
204
205 void addZeros(std::vector<llvm::Constant*>& inits, size_t pos, size_t offset)
206 {
207 assert(offset > pos);
208 size_t diff = offset - pos;
209
210 size_t sz;
211
212 do
213 {
214 if (pos%8 == 0 && diff >= 8)
215 sz = 8;
216 else if (pos%4 == 0 && diff >= 4)
217 sz = 4;
218 else if (pos%2 == 0 && diff >= 2)
219 sz = 2;
220 else // if (pos % 1 == 0)
221 sz = 1;
222 inits.push_back(LLConstant::getNullValue(LLIntegerType::get(sz*8)));
223 pos += sz;
224 diff -= sz;
225 } while (pos < offset);
226
227 assert(pos == offset);
228 }
229
230 // FIXME: body is exact copy of above
231 void addZeros(std::vector<llvm::Value*>& inits, size_t pos, size_t offset)
232 {
233 assert(offset > pos);
234 size_t diff = offset - pos;
235
236 size_t sz;
237
238 do
239 {
240 if (pos%8 == 0 && diff >= 8)
241 sz = 8;
242 else if (pos%4 == 0 && diff >= 4)
243 sz = 4;
244 else if (pos%2 == 0 && diff >= 2)
245 sz = 2;
246 else // if (pos % 1 == 0)
247 sz = 1;
248 inits.push_back(LLConstant::getNullValue(LLIntegerType::get(sz*8)));
249 pos += sz;
250 diff -= sz;
251 } while (pos < offset);
252
253 assert(pos == offset);
254 }
255
256 void IrStruct::buildDefaultConstInit(std::vector<llvm::Constant*>& inits)
257 {
258 assert(!defaultFound);
259 defaultFound = true;
260
261 const llvm::StructType* structtype = isaStruct(aggrdecl->type->ir.type->get());
262 Logger::cout() << "struct type: " << *structtype << '\n';
263
264 size_t lastoffset = 0;
265 size_t lastsize = 0;
266
267 {
268 Logger::println("Find the default fields");
269 LOG_SCOPE;
270
271 // go through all vars and find the ones that contribute to the default
272 size_t nvars = varDecls.size();
273 for (size_t i=0; i<nvars; i++)
274 {
275 VarDeclaration* var = varDecls[i];
276
277 Logger::println("field %s %s = %s : +%u", var->type->toChars(), var->toChars(), var->init ? var->init->toChars() : var->type->defaultInit(var->loc)->toChars(), var->offset);
278
279 // only add vars that don't overlap
280 size_t offset = var->offset;
281 size_t size = var->type->size();
282 if (offset >= lastoffset+lastsize)
283 {
284 Logger::println(" added");
285 lastoffset = offset;
286 lastsize = size;
287 defVars.push_back(var);
288 }
289 }
290 }
291
292 {
293 Logger::println("Build the default initializer");
294 LOG_SCOPE;
295
296 lastoffset = 0;
297 lastsize = 0;
298
299 // go through the default vars and build the default constant initializer
300 // adding zeros along the way to live up to alignment expectations
301 size_t nvars = defVars.size();
302 for (size_t i=0; i<nvars; i++)
303 {
304 VarDeclaration* var = defVars[i];
305
306 Logger::println("field %s %s = %s : +%u", var->type->toChars(), var->toChars(), var->init ? var->init->toChars() : var->type->defaultInit(var->loc)->toChars(), var->offset);
307
308 // get offset and size
309 size_t offset = var->offset;
310 size_t size = var->type->size();
311
312 // is there space in between last last offset and this one?
313 // if so, fill it with zeros
314 if (offset > lastoffset+lastsize)
315 {
316 size_t pos = lastoffset + lastsize;
317 addZeros(inits, pos, offset);
318 }
319
320 // add the field
321 assert(var->ir.irField->constInit);
322 inits.push_back(var->ir.irField->constInit);
323
324 lastoffset = offset;
325 lastsize = var->type->size();
326 }
327
328 // there might still be padding after the last one, make sure that is zeroed as well
329 // is there space in between last last offset and this one?
330 size_t structsize = getABITypeSize(structtype);
331
332 if (structsize > lastoffset+lastsize)
333 {
334 size_t pos = lastoffset + lastsize;
335 addZeros(inits, pos, structsize);
336 }
337 }
338 }
339
340 LLConstant* IrStruct::buildDefaultConstInit()
341 {
342 // doesn't work for classes, they add stuff before and maybe after data fields
343 assert(!aggrdecl->isClassDeclaration());
344
345 // initializer llvm constant list
346 std::vector<LLConstant*> inits;
347
348 // just start with an empty list
349 buildDefaultConstInit(inits);
350
351 // build the constant
352 // note that the type matches the initializer, not the aggregate in cases with unions
353 LLConstant* c = LLConstantStruct::get(inits, aggrdecl->ir.irStruct->packed);
354 Logger::cout() << "llvm constant: " << *c << '\n';
355 // assert(0);
356 return c;
357 }