Mercurial > projects > ldc
comparison gen/structs.cpp @ 136:0e28624814e8 trunk
[svn r140] did a lot of the work towards being able to pass multiple modules on the command line. not complete yet though
author | lindquist |
---|---|
date | Thu, 17 Jan 2008 03:15:12 +0100 |
parents | 44a95ac7368a |
children | ce7b81fb957f |
comparison
equal
deleted
inserted
replaced
135:176bd52b3cf5 | 136:0e28624814e8 |
---|---|
10 #include "gen/irstate.h" | 10 #include "gen/irstate.h" |
11 #include "gen/tollvm.h" | 11 #include "gen/tollvm.h" |
12 #include "gen/arrays.h" | 12 #include "gen/arrays.h" |
13 #include "gen/logger.h" | 13 #include "gen/logger.h" |
14 #include "gen/structs.h" | 14 #include "gen/structs.h" |
15 | |
16 #include "ir/irstruct.h" | |
15 | 17 |
16 ////////////////////////////////////////////////////////////////////////////////////////// | 18 ////////////////////////////////////////////////////////////////////////////////////////// |
17 | 19 |
18 const llvm::Type* DtoStructType(Type* t) | 20 const llvm::Type* DtoStructType(Type* t) |
19 { | 21 { |
91 Initializer* ini = (Initializer*)si->value.data[i]; | 93 Initializer* ini = (Initializer*)si->value.data[i]; |
92 assert(ini); | 94 assert(ini); |
93 VarDeclaration* vd = (VarDeclaration*)si->vars.data[i]; | 95 VarDeclaration* vd = (VarDeclaration*)si->vars.data[i]; |
94 assert(vd); | 96 assert(vd); |
95 llvm::Constant* v = DtoConstInitializer(vd->type, ini); | 97 llvm::Constant* v = DtoConstInitializer(vd->type, ini); |
96 inits.push_back(DUnionIdx(vd->llvmFieldIndex, vd->llvmFieldIndexOffset, v)); | 98 inits.push_back(DUnionIdx(vd->irField->index, vd->irField->indexOffset, v)); |
97 } | 99 } |
98 | 100 |
99 DtoConstInitStruct((StructDeclaration*)si->ad); | 101 DtoConstInitStruct((StructDeclaration*)si->ad); |
100 return si->ad->llvmUnion->getConst(inits); | 102 return si->ad->llvmUnion->getConst(inits); |
101 } | 103 } |
119 | 121 |
120 for (unsigned i=0; i<sd->fields.dim; ++i) { | 122 for (unsigned i=0; i<sd->fields.dim; ++i) { |
121 VarDeclaration* vd = (VarDeclaration*)sd->fields.data[i]; | 123 VarDeclaration* vd = (VarDeclaration*)sd->fields.data[i]; |
122 Type* vdtype = DtoDType(vd->type); | 124 Type* vdtype = DtoDType(vd->type); |
123 Logger::println("found %u type %s", vd->offset, vdtype->toChars()); | 125 Logger::println("found %u type %s", vd->offset, vdtype->toChars()); |
124 assert(vd->llvmFieldIndex >= 0); | 126 assert(vd->irField->index >= 0); |
125 if (os == vd->offset && vdtype == t) { | 127 if (os == vd->offset && vdtype == t) { |
126 idxs.push_back(vd->llvmFieldIndex); | 128 idxs.push_back(vd->irField->index); |
127 ptr = DtoGEP(ptr, idxs, "tmp"); | 129 ptr = DtoGEP(ptr, idxs, "tmp"); |
128 if (ptr->getType() != llt) | 130 if (ptr->getType() != llt) |
129 ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp"); | 131 ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp"); |
130 if (vd->llvmFieldIndexOffset) | 132 if (vd->irField->indexOffset) |
131 ptr = new llvm::GetElementPtrInst(ptr, DtoConstUint(vd->llvmFieldIndexOffset), "tmp", gIR->scopebb()); | 133 ptr = new llvm::GetElementPtrInst(ptr, DtoConstUint(vd->irField->indexOffset), "tmp", gIR->scopebb()); |
132 return ptr; | 134 return ptr; |
133 } | 135 } |
134 else if (vdtype->ty == Tstruct && (vd->offset + vdtype->size()) > os) { | 136 else if (vdtype->ty == Tstruct && (vd->offset + vdtype->size()) > os) { |
135 TypeStruct* ts = (TypeStruct*)vdtype; | 137 TypeStruct* ts = (TypeStruct*)vdtype; |
136 StructDeclaration* ssd = ts->sym; | 138 StructDeclaration* ssd = ts->sym; |
137 idxs.push_back(vd->llvmFieldIndex); | 139 idxs.push_back(vd->irField->index); |
138 if (vd->llvmFieldIndexOffset) { | 140 if (vd->irField->indexOffset) { |
139 Logger::println("has union field offset"); | 141 Logger::println("has union field offset"); |
140 ptr = DtoGEP(ptr, idxs, "tmp"); | 142 ptr = DtoGEP(ptr, idxs, "tmp"); |
141 if (ptr->getType() != llt) | 143 if (ptr->getType() != llt) |
142 ptr = DtoBitCast(ptr, llt); | 144 ptr = DtoBitCast(ptr, llt); |
143 ptr = new llvm::GetElementPtrInst(ptr, DtoConstUint(vd->llvmFieldIndexOffset), "tmp", gIR->scopebb()); | 145 ptr = new llvm::GetElementPtrInst(ptr, DtoConstUint(vd->irField->indexOffset), "tmp", gIR->scopebb()); |
144 std::vector<unsigned> tmp; | 146 std::vector<unsigned> tmp; |
145 return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp); | 147 return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp); |
146 } | 148 } |
147 else { | 149 else { |
148 const llvm::Type* sty = getPtrToType(DtoType(vd->type)); | 150 const llvm::Type* sty = getPtrToType(DtoType(vd->type)); |
174 Logger::println("DtoResolveStruct(%s): %s", sd->toChars(), sd->loc.toChars()); | 176 Logger::println("DtoResolveStruct(%s): %s", sd->toChars(), sd->loc.toChars()); |
175 LOG_SCOPE; | 177 LOG_SCOPE; |
176 | 178 |
177 TypeStruct* ts = (TypeStruct*)DtoDType(sd->type); | 179 TypeStruct* ts = (TypeStruct*)DtoDType(sd->type); |
178 | 180 |
179 IRStruct* irstruct = new IRStruct(ts); | 181 IrStruct* irstruct = new IrStruct(ts); |
180 sd->llvmIRStruct = irstruct; | 182 sd->llvmIrStruct = irstruct; |
181 gIR->structs.push_back(irstruct); | 183 gIR->structs.push_back(irstruct); |
182 | 184 |
183 // fields | 185 // fields |
184 Array* arr = &sd->fields; | 186 Array* arr = &sd->fields; |
185 for (int k=0; k < arr->dim; k++) { | 187 for (int k=0; k < arr->dim; k++) { |
231 unsigned lastoffset = (unsigned)-1; | 233 unsigned lastoffset = (unsigned)-1; |
232 const llvm::Type* fieldtype = NULL; | 234 const llvm::Type* fieldtype = NULL; |
233 VarDeclaration* fieldinit = NULL; | 235 VarDeclaration* fieldinit = NULL; |
234 size_t fieldpad = 0; | 236 size_t fieldpad = 0; |
235 int idx = 0; | 237 int idx = 0; |
236 for (IRStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) { | 238 for (IrStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) { |
237 // first iteration | 239 // first iteration |
238 if (lastoffset == (unsigned)-1) { | 240 if (lastoffset == (unsigned)-1) { |
239 lastoffset = i->first; | 241 lastoffset = i->first; |
240 assert(lastoffset == 0); | 242 assert(lastoffset == 0); |
241 fieldtype = i->second.type; | 243 fieldtype = i->second.type; |
242 fieldinit = i->second.var; | 244 fieldinit = i->second.var; |
243 prevsize = getABITypeSize(fieldtype); | 245 prevsize = getABITypeSize(fieldtype); |
244 i->second.var->llvmFieldIndex = idx; | 246 i->second.var->irField->index = idx; |
245 } | 247 } |
246 // colliding offset? | 248 // colliding offset? |
247 else if (lastoffset == i->first) { | 249 else if (lastoffset == i->first) { |
248 size_t s = getABITypeSize(i->second.type); | 250 size_t s = getABITypeSize(i->second.type); |
249 if (s > prevsize) { | 251 if (s > prevsize) { |
250 fieldpad += s - prevsize; | 252 fieldpad += s - prevsize; |
251 prevsize = s; | 253 prevsize = s; |
252 } | 254 } |
253 sd->llvmHasUnions = true; | 255 sd->llvmHasUnions = true; |
254 i->second.var->llvmFieldIndex = idx; | 256 i->second.var->irField->index = idx; |
255 } | 257 } |
256 // intersecting offset? | 258 // intersecting offset? |
257 else if (i->first < (lastoffset + prevsize)) { | 259 else if (i->first < (lastoffset + prevsize)) { |
258 size_t s = getABITypeSize(i->second.type); | 260 size_t s = getABITypeSize(i->second.type); |
259 assert((i->first + s) <= (lastoffset + prevsize)); // this holds because all types are aligned to their size | 261 assert((i->first + s) <= (lastoffset + prevsize)); // this holds because all types are aligned to their size |
260 sd->llvmHasUnions = true; | 262 sd->llvmHasUnions = true; |
261 i->second.var->llvmFieldIndex = idx; | 263 i->second.var->irField->index = idx; |
262 i->second.var->llvmFieldIndexOffset = (i->first - lastoffset) / s; | 264 i->second.var->irField->indexOffset = (i->first - lastoffset) / s; |
263 } | 265 } |
264 // fresh offset | 266 // fresh offset |
265 else { | 267 else { |
266 // commit the field | 268 // commit the field |
267 fieldtypes.push_back(fieldtype); | 269 fieldtypes.push_back(fieldtype); |
277 // start new | 279 // start new |
278 lastoffset = i->first; | 280 lastoffset = i->first; |
279 fieldtype = i->second.type; | 281 fieldtype = i->second.type; |
280 fieldinit = i->second.var; | 282 fieldinit = i->second.var; |
281 prevsize = getABITypeSize(fieldtype); | 283 prevsize = getABITypeSize(fieldtype); |
282 i->second.var->llvmFieldIndex = idx; | 284 i->second.var->irField->index = idx; |
283 fieldpad = 0; | 285 fieldpad = 0; |
284 } | 286 } |
285 } | 287 } |
286 fieldtypes.push_back(fieldtype); | 288 fieldtypes.push_back(fieldtype); |
287 irstruct->defaultFields.push_back(fieldinit); | 289 irstruct->defaultFields.push_back(fieldinit); |
347 sd->llvmInitialized = true; | 349 sd->llvmInitialized = true; |
348 | 350 |
349 Logger::println("DtoConstInitStruct(%s): %s", sd->toChars(), sd->loc.toChars()); | 351 Logger::println("DtoConstInitStruct(%s): %s", sd->toChars(), sd->loc.toChars()); |
350 LOG_SCOPE; | 352 LOG_SCOPE; |
351 | 353 |
352 IRStruct* irstruct = sd->llvmIRStruct; | 354 IrStruct* irstruct = sd->llvmIrStruct; |
353 gIR->structs.push_back(irstruct); | 355 gIR->structs.push_back(irstruct); |
354 | 356 |
355 // make sure each offset knows its default initializer | 357 // make sure each offset knows its default initializer |
356 for (IRStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) | 358 for (IrStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) |
357 { | 359 { |
358 IRStruct::Offset* so = &i->second; | 360 IrStruct::Offset* so = &i->second; |
359 llvm::Constant* finit = DtoConstFieldInitializer(so->var->type, so->var->init); | 361 llvm::Constant* finit = DtoConstFieldInitializer(so->var->type, so->var->init); |
360 so->init = finit; | 362 so->init = finit; |
361 so->var->llvmConstInit = finit; | 363 so->var->irField->constInit = finit; |
362 } | 364 } |
363 | 365 |
364 const llvm::StructType* structtype = isaStruct(sd->type->llvmType->get()); | 366 const llvm::StructType* structtype = isaStruct(sd->type->llvmType->get()); |
365 | 367 |
366 // go through the field inits and build the default initializer | 368 // go through the field inits and build the default initializer |
367 std::vector<llvm::Constant*> fieldinits_ll; | 369 std::vector<llvm::Constant*> fieldinits_ll; |
368 size_t nfi = irstruct->defaultFields.size(); | 370 size_t nfi = irstruct->defaultFields.size(); |
369 for (size_t i=0; i<nfi; ++i) { | 371 for (size_t i=0; i<nfi; ++i) { |
370 llvm::Constant* c; | 372 llvm::Constant* c; |
371 if (irstruct->defaultFields[i] != NULL) { | 373 if (irstruct->defaultFields[i] != NULL) { |
372 c = irstruct->defaultFields[i]->llvmConstInit; | 374 c = irstruct->defaultFields[i]->irField->constInit; |
373 assert(c); | 375 assert(c); |
374 } | 376 } |
375 else { | 377 else { |
376 const llvm::ArrayType* arrty = isaArray(structtype->getElementType(i)); | 378 const llvm::ArrayType* arrty = isaArray(structtype->getElementType(i)); |
377 std::vector<llvm::Constant*> vals(arrty->getNumElements(), llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false)); | 379 std::vector<llvm::Constant*> vals(arrty->getNumElements(), llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false)); |
433 ////////////////////////////////////////////////////////////////////////////////////////// | 435 ////////////////////////////////////////////////////////////////////////////////////////// |
434 | 436 |
435 DUnion::DUnion() | 437 DUnion::DUnion() |
436 { | 438 { |
437 DUnionField* f = NULL; | 439 DUnionField* f = NULL; |
438 IRStruct* topstruct = gIR->topstruct(); | 440 IrStruct* topstruct = gIR->topstruct(); |
439 bool unions = false; | 441 bool unions = false; |
440 for (IRStruct::OffsetMap::iterator i=topstruct->offsets.begin(); i!=topstruct->offsets.end(); ++i) | 442 for (IrStruct::OffsetMap::iterator i=topstruct->offsets.begin(); i!=topstruct->offsets.end(); ++i) |
441 { | 443 { |
442 unsigned o = i->first; | 444 unsigned o = i->first; |
443 IRStruct::Offset* so = &i->second; | 445 IrStruct::Offset* so = &i->second; |
444 const llvm::Type* ft = so->init->getType(); | 446 const llvm::Type* ft = so->init->getType(); |
445 size_t sz = getABITypeSize(ft); | 447 size_t sz = getABITypeSize(ft); |
446 if (f == NULL) { // new field | 448 if (f == NULL) { // new field |
447 fields.push_back(DUnionField()); | 449 fields.push_back(DUnionField()); |
448 f = &fields.back(); | 450 f = &fields.back(); |