comparison ir/irtypeclass.cpp @ 1270:dd135ff697fa

Fixed class default initializers and type generation. Bug #260 is fixed.
author Tomas Lindquist Olsen <tomas.l.olsen gmail com>
date Mon, 27 Apr 2009 03:40:40 +0200
parents bbe6d2b87842
children 8fb39f7f1a7c
comparison
equal deleted inserted replaced
1269:b8a51aa44d4c 1270:dd135ff697fa
12 #include "ir/irtypeclass.h" 12 #include "ir/irtypeclass.h"
13 13
14 ////////////////////////////////////////////////////////////////////////////// 14 //////////////////////////////////////////////////////////////////////////////
15 15
16 extern size_t add_zeros(std::vector<const llvm::Type*>& defaultTypes, size_t diff); 16 extern size_t add_zeros(std::vector<const llvm::Type*>& defaultTypes, size_t diff);
17 extern bool var_offset_sort_cb(const VarDeclaration* v1, const VarDeclaration* v2);
17 18
18 ////////////////////////////////////////////////////////////////////////////// 19 //////////////////////////////////////////////////////////////////////////////
19 20
20 IrTypeClass::IrTypeClass(ClassDeclaration* cd) 21 IrTypeClass::IrTypeClass(ClassDeclaration* cd)
21 : IrTypeAggr(cd), 22 : IrTypeAggr(cd),
38 if (base->baseClass) 39 if (base->baseClass)
39 { 40 {
40 addBaseClassData(defaultTypes, base->baseClass, offset, field_index); 41 addBaseClassData(defaultTypes, base->baseClass, offset, field_index);
41 } 42 }
42 43
43 ArrayIter<VarDeclaration> it(base->fields); 44 // FIXME: merge code with structs in IrTypeAggr
44 for (; !it.done(); it.next()) 45
45 { 46 // mirror the sd->fields array but only fill in contributors
46 VarDeclaration* vd = it.get(); 47 size_t n = base->fields.dim;
47 48 LLSmallVector<VarDeclaration*, 16> data(n, NULL);
48 // skip if offset moved backwards 49 default_fields.reserve(n);
49 if (vd->offset < offset) 50
50 { 51 // first fill in the fields with explicit initializers
51 IF_LOG Logger::println("Skipping field %s %s (+%u) for default", vd->type->toChars(), vd->toChars(), vd->offset); 52 VarDeclarationIter field_it(base->fields);
52 if (vd->ir.irField == NULL) 53 for (; field_it.more(); field_it.next())
54 {
55 // init is !null for explicit inits
56 if (field_it->init != NULL)
57 {
58 IF_LOG Logger::println("adding explicit initializer for struct field %s",
59 field_it->toChars());
60
61 data[field_it.index] = *field_it;
62
63 size_t f_begin = field_it->offset;
64 size_t f_end = f_begin + field_it->type->size();
65
66 // make sure there is no overlap
67 for (size_t i = 0; i < field_it.index; i++)
53 { 68 {
54 new IrField(vd, 2, vd->offset - PTRSIZE * 2); 69 if (data[i] != NULL)
70 {
71 VarDeclaration* vd = data[i];
72 size_t v_begin = vd->offset;
73 size_t v_end = v_begin + vd->type->size();
74
75 if (v_begin >= f_end || v_end <= f_begin)
76 continue;
77
78 base->error(vd->loc, "has overlapping initialization for %s and %s",
79 field_it->toChars(), vd->toChars());
80 }
55 } 81 }
82 }
83 }
84
85 if (global.errors)
86 {
87 fatal();
88 }
89
90 // fill in default initializers
91 field_it = VarDeclarationIter(base->fields);
92 for (;field_it.more(); field_it.next())
93 {
94 if (data[field_it.index])
56 continue; 95 continue;
57 } 96
58 97 size_t f_begin = field_it->offset;
59 IF_LOG Logger::println("Adding default field %s %s (+%u)", vd->type->toChars(), vd->toChars(), vd->offset); 98 size_t f_end = f_begin + field_it->type->size();
99
100 // make sure it doesn't overlap anything explicit
101 bool overlaps = false;
102 for (size_t i = 0; i < n; i++)
103 {
104 if (data[i])
105 {
106 size_t v_begin = data[i]->offset;
107 size_t v_end = v_begin + data[i]->type->size();
108
109 if (v_begin >= f_end || v_end <= f_begin)
110 continue;
111
112 overlaps = true;
113 break;
114 }
115 }
116
117 // if no overlap was found, add the default initializer
118 if (!overlaps)
119 {
120 IF_LOG Logger::println("adding default initializer for struct field %s",
121 field_it->toChars());
122 data[field_it.index] = *field_it;
123 }
124 }
125
126 // ok. now we can build a list of llvm types. and make sure zeros are inserted if necessary.
127
128 // first we sort the list by offset
129 std::sort(data.begin(), data.end(), var_offset_sort_cb);
130
131 // add types to list
132 for (size_t i = 0; i < n; i++)
133 {
134 VarDeclaration* vd = data[i];
135
136 if (vd == NULL)
137 continue;
138
139 assert(vd->offset >= offset && "it's a bug...");
140
141 // add to default field list
142 if (cd == base)
143 default_fields.push_back(vd);
60 144
61 // get next aligned offset for this type 145 // get next aligned offset for this type
62 size_t alignsize = vd->type->alignsize(); 146 size_t alignsize = vd->type->alignsize();
63 size_t alignedoffset = (offset + alignsize - 1) & ~(alignsize - 1); 147 size_t alignedoffset = (offset + alignsize - 1) & ~(alignsize - 1);
64 148
65 // do we need to insert explicit padding before the field? 149 // insert explicit padding?
66 if (alignedoffset < vd->offset) 150 if (alignedoffset < vd->offset)
67 { 151 {
68 field_index += add_zeros(defaultTypes, vd->offset - alignedoffset); 152 field_index += add_zeros(defaultTypes, vd->offset - alignedoffset);
69 } 153 }
70 154
72 defaultTypes.push_back(DtoType(vd->type)); 156 defaultTypes.push_back(DtoType(vd->type));
73 157
74 // advance offset to right past this field 158 // advance offset to right past this field
75 offset = vd->offset + vd->type->size(); 159 offset = vd->offset + vd->type->size();
76 160
77 // give field index 161 // create ir field
78 // the IrField creation doesn't really belong here, but it's a trivial operation
79 // and it save yet another of these loops.
80 IF_LOG Logger::println("Field index: %zu", field_index);
81 if (vd->ir.irField == NULL) 162 if (vd->ir.irField == NULL)
82 {
83 new IrField(vd, field_index); 163 new IrField(vd, field_index);
84 } 164 else
165 assert(vd->ir.irField->index == field_index &&
166 vd->ir.irField->unionOffset == 0 &&
167 "inconsistent field data");
85 field_index++; 168 field_index++;
86 } 169 }
87 170
171 // make sure all fields really get their ir field
172 ArrayIter<VarDeclaration> it(base->fields);
173 for (; !it.done(); it.next())
174 {
175 VarDeclaration* vd = it.get();
176 if (vd->ir.irField == NULL)
177 new IrField(vd, 0, vd->offset);
178 }
179
88 // any interface implementations? 180 // any interface implementations?
89 if (base->vtblInterfaces) 181 if (base->vtblInterfaces && base->vtblInterfaces->dim > 0)
90 { 182 {
91 bool new_instances = (base == cd); 183 bool new_instances = (base == cd);
92 184
93 ArrayIter<BaseClass> it2(*base->vtblInterfaces); 185 ArrayIter<BaseClass> it2(*base->vtblInterfaces);
94 186
95 VarDeclarationIter interfaces_idx(ClassDeclaration::classinfo->fields, 3); 187 VarDeclarationIter interfaces_idx(ClassDeclaration::classinfo->fields, 3);
96 Type* first = interfaces_idx->type->next->pointerTo(); 188 Type* first = interfaces_idx->type->next->pointerTo();
189
190 // align offset
191 offset = (offset + PTRSIZE - 1) & ~(PTRSIZE - 1);
97 192
98 for (; !it2.done(); it2.next()) 193 for (; !it2.done(); it2.next())
99 { 194 {
100 BaseClass* b = it2.get(); 195 BaseClass* b = it2.get();
101 IF_LOG Logger::println("Adding interface vtbl for %s", b->base->toPrettyChars()); 196 IF_LOG Logger::println("Adding interface vtbl for %s", b->base->toPrettyChars());
115 // inc count 210 // inc count
116 num_interface_vtbls++; 211 num_interface_vtbls++;
117 } 212 }
118 } 213 }
119 214
215 #if 0
120 // tail padding? 216 // tail padding?
121 if (offset < base->structsize) 217 if (offset < base->structsize)
122 { 218 {
123 field_index += add_zeros(defaultTypes, base->structsize - offset); 219 field_index += add_zeros(defaultTypes, base->structsize - offset);
124 offset = base->structsize; 220 offset = base->structsize;
125 } 221 }
222 #endif
126 } 223 }
127 224
128 ////////////////////////////////////////////////////////////////////////////// 225 //////////////////////////////////////////////////////////////////////////////
129 226
130 const llvm::Type* IrTypeClass::buildType() 227 const llvm::Type* IrTypeClass::buildType()
157 size_t offset = PTRSIZE * 2; 254 size_t offset = PTRSIZE * 2;
158 size_t field_index = 2; 255 size_t field_index = 2;
159 256
160 // add data members recursively 257 // add data members recursively
161 addBaseClassData(defaultTypes, cd, offset, field_index); 258 addBaseClassData(defaultTypes, cd, offset, field_index);
259
260 #if 1
261 // tail padding?
262 if (offset < cd->structsize)
263 {
264 field_index += add_zeros(defaultTypes, cd->structsize - offset);
265 offset = cd->structsize;
266 }
267 #endif
162 } 268 }
163 269
164 // errors are fatal during codegen 270 // errors are fatal during codegen
165 if (global.errors) 271 if (global.errors)
166 fatal(); 272 fatal();