Mercurial > projects > ldc
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 ////////////////////////////////////////////////////////////////////////////// |