comparison ir/irtypeclass.cpp @ 1228:79758fd2f48a

Added Doxygen file. Completely seperated type and symbol generation. Should fix a lot of bugs, but is not yet 100% complete.
author Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
date Wed, 15 Apr 2009 20:06:25 +0200
parents
children e67c85d6e680
comparison
equal deleted inserted replaced
1215:08f87d8cd101 1228:79758fd2f48a
1 #include "llvm/DerivedTypes.h"
2
3 #include "aggregate.h"
4 #include "declaration.h"
5 #include "dsymbol.h"
6 #include "mtype.h"
7
8 #include "gen/irstate.h"
9 #include "gen/logger.h"
10 #include "gen/tollvm.h"
11 #include "gen/utils.h"
12 #include "ir/irtypeclass.h"
13
14 //////////////////////////////////////////////////////////////////////////////
15
16 extern size_t add_zeros(std::vector<const llvm::Type*>& defaultTypes, size_t diff);
17
18 //////////////////////////////////////////////////////////////////////////////
19
20 IrTypeClass::IrTypeClass(ClassDeclaration* cd)
21 : IrTypeAggr(cd),
22 cd(cd),
23 tc((TypeClass*)cd->type),
24 vtbl_pa(llvm::OpaqueType::get())
25 {
26 vtbl_size = cd->vtbl.dim;
27 }
28
29 //////////////////////////////////////////////////////////////////////////////
30
31 void IrTypeClass::addBaseClassData(
32 std::vector< const llvm::Type * > & defaultTypes,
33 ClassDeclaration * base,
34 size_t & offset,
35 size_t & field_index)
36 {
37 if (base->baseClass)
38 {
39 addBaseClassData(defaultTypes, base->baseClass, offset, field_index);
40 }
41
42 ArrayIter<VarDeclaration> it(base->fields);
43 for (; !it.done(); it.next())
44 {
45 VarDeclaration* vd = it.get();
46
47 // skip if offset moved backwards
48 if (vd->offset < offset)
49 {
50 IF_LOG Logger::println("Skipping field %s %s (+%u) for default", vd->type->toChars(), vd->toChars(), vd->offset);
51 if (vd->ir.irField == NULL)
52 {
53 new IrField(vd, 2, vd->offset - PTRSIZE * 2);
54 }
55 continue;
56 }
57
58 IF_LOG Logger::println("Adding default field %s %s (+%u)", vd->type->toChars(), vd->toChars(), vd->offset);
59
60 // get next aligned offset for this type
61 size_t alignsize = vd->type->alignsize();
62 size_t alignedoffset = (offset + alignsize - 1) & ~(alignsize - 1);
63
64 // do we need to insert explicit padding before the field?
65 if (alignedoffset < vd->offset)
66 {
67 field_index += add_zeros(defaultTypes, vd->offset - alignedoffset);
68 }
69
70 // add default type
71 defaultTypes.push_back(DtoType(vd->type));
72
73 // advance offset to right past this field
74 offset = vd->offset + vd->type->size();
75
76 // give field index
77 // the IrField creation doesn't really belong here, but it's a trivial operation
78 // and it save yet another of these loops.
79 IF_LOG Logger::println("Field index: %zu", field_index);
80 if (vd->ir.irField == NULL)
81 {
82 new IrField(vd, field_index);
83 }
84 field_index++;
85 }
86
87 // any interface implementations?
88 if (base->vtblInterfaces)
89 {
90 bool new_instances = (base == cd);
91
92 ArrayIter<BaseClass> it2(*base->vtblInterfaces);
93
94 for (; !it2.done(); it2.next())
95 {
96 BaseClass* b = it2.get();
97 IF_LOG Logger::println("Adding interface vtbl for %s", b->base->toPrettyChars());
98
99 Array arr;
100 b->fillVtbl(cd, &arr, new_instances);
101
102 const llvm::Type* ivtbl_type = buildVtblType(Type::tvoid->pointerTo(), &arr);
103 defaultTypes.push_back(llvm::PointerType::get(ivtbl_type, 0));
104
105 offset += PTRSIZE;
106
107 // add to the interface map
108 if (interfaceMap.find(b->base) == interfaceMap.end())
109 interfaceMap.insert(std::make_pair(b->base, field_index));
110 field_index++;
111 }
112 }
113
114 // tail padding?
115 if (offset < base->structsize)
116 {
117 field_index += add_zeros(defaultTypes, base->structsize - offset);
118 offset = base->structsize;
119 }
120 }
121
122 //////////////////////////////////////////////////////////////////////////////
123
124 const llvm::Type* IrTypeClass::buildType()
125 {
126 IF_LOG Logger::println("Building class type %s @ %s", cd->toPrettyChars(), cd->locToChars());
127 LOG_SCOPE;
128 IF_LOG Logger::println("Instance size: %u", cd->structsize);
129
130 // find the fields that contribute to the default initializer.
131 // these will define the default type.
132
133 std::vector<const llvm::Type*> defaultTypes;
134 defaultTypes.reserve(32);
135
136 // add vtbl
137 defaultTypes.push_back(llvm::PointerType::get(vtbl_pa.get(), 0));
138
139 // interface are just a vtable
140 if (!cd->isInterfaceDeclaration())
141 {
142 // add monitor
143 defaultTypes.push_back(llvm::PointerType::get(llvm::Type::Int8Ty, 0));
144
145 // we start right after the vtbl and monitor
146 size_t offset = PTRSIZE * 2;
147 size_t field_index = 2;
148
149 // add data members recursively
150 addBaseClassData(defaultTypes, cd, offset, field_index);
151 }
152
153 // errors are fatal during codegen
154 if (global.errors)
155 fatal();
156
157 // build the llvm type
158 const llvm::Type* st = llvm::StructType::get(defaultTypes, false);
159
160 // refine type
161 llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(st);
162
163 // name type
164 Type::sir->getState()->module->addTypeName(cd->toPrettyChars(), pa.get());
165
166 // VTBL
167
168 // build vtbl type
169 const llvm::Type* vtblty = buildVtblType(
170 ClassDeclaration::classinfo->type,
171 &cd->vtbl);
172
173 // refine vtbl pa
174 llvm::cast<llvm::OpaqueType>(vtbl_pa.get())->refineAbstractTypeTo(vtblty);
175
176 // name vtbl type
177 std::string name(cd->toPrettyChars());
178 name.append(".__vtbl");
179 Type::sir->getState()->module->addTypeName(name, vtbl_pa.get());
180
181 #if 0
182 IF_LOG Logger::cout() << "class type: " << *pa.get() << std::endl;
183 #endif
184
185 return get();
186 }
187
188 //////////////////////////////////////////////////////////////////////////////
189
190 const llvm::Type* IrTypeClass::buildVtblType(Type* first, Array* vtbl_array)
191 {
192 IF_LOG Logger::println("Building vtbl type for class %s", cd->toPrettyChars());
193 LOG_SCOPE;
194
195 std::vector<const llvm::Type*> types;
196 types.reserve(vtbl_array->dim);
197
198 // first comes the classinfo
199 types.push_back(DtoType(first));
200
201 // then come the functions
202 ArrayIter<Dsymbol> it(*vtbl_array);
203 it.index = 1;
204
205 for (; !it.done(); it.next())
206 {
207 FuncDeclaration* fd = it.get()->isFuncDeclaration();
208 assert(fd && "invalid vtbl entry");
209
210 IF_LOG Logger::println("Adding type of %s", fd->toPrettyChars());
211
212 types.push_back(DtoType(fd->type->pointerTo()));
213 }
214
215 // build the vtbl llvm type
216 return llvm::StructType::get(types, false);
217 }
218
219 //////////////////////////////////////////////////////////////////////////////
220
221 const llvm::Type * IrTypeClass::get()
222 {
223 return llvm::PointerType::get(pa.get(), 0);
224 }
225
226 //////////////////////////////////////////////////////////////////////////////
227
228 size_t IrTypeClass::getInterfaceIndex(ClassDeclaration * inter)
229 {
230 ClassIndexMap::iterator it = interfaceMap.find(inter);
231 if (it == interfaceMap.end())
232 return ~0;
233 return it->second;
234 }
235
236 //////////////////////////////////////////////////////////////////////////////