comparison gen/structs.cpp @ 1353:45aca7e7cc88

Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
author Frits van Bommel <fvbommel wxs.nl>
date Thu, 14 May 2009 20:36:55 +0200
parents c8b9406d84ca
children 8ca25bd765a3
comparison
equal deleted inserted replaced
1352:b9f5f7c5db73 1353:45aca7e7cc88
1 #include <algorithm> 1 #include <algorithm>
2 2
3 #include "gen/llvm.h" 3 #include "gen/llvm.h"
4 #include "llvm/AbstractTypeUser.h"
5 #include "llvm/ADT/DenseMap.h"
4 6
5 #include "mtype.h" 7 #include "mtype.h"
6 #include "aggregate.h" 8 #include "aggregate.h"
7 #include "init.h" 9 #include "init.h"
8 #include "declaration.h" 10 #include "declaration.h"
330 } 332 }
331 333
332 return values; 334 return values;
333 } 335 }
334 336
337 /// Return the type returned by DtoUnpaddedStruct called on a value of the
338 /// specified type.
339 /// Union types will get expanded into a struct, with a type for each member.
340 LLType* DtoUnpaddedStructType(Type* dty) {
341 assert(dty->ty == Tstruct);
342
343 typedef llvm::DenseMap<Type*, llvm::PATypeHolder> CacheT;
344 static CacheT cache;
345 CacheT::iterator it = cache.find(dty);
346 if (it != cache.end())
347 return it->second;
348
349 TypeStruct* sty = (TypeStruct*) dty;
350 Array& fields = sty->sym->fields;
351
352 std::vector<const LLType*> types;
353
354 for (unsigned i = 0; i < fields.dim; i++) {
355 VarDeclaration* vd = (VarDeclaration*) fields.data[i];
356 const LLType* fty;
357 if (vd->type->ty == Tstruct) {
358 // Nested structs are the only members that can contain padding
359 fty = DtoUnpaddedStructType(vd->type);
360 } else {
361 fty = DtoType(vd->type);
362 }
363 types.push_back(fty);
364 }
365 LLType* Ty = LLStructType::get(types);
366 cache.insert(std::make_pair(dty, Ty));
367 return Ty;
368 }
369
370 /// Return the struct value represented by v without the padding fields.
371 /// Unions will be expanded, with a value for each member.
372 /// Note: v must be a pointer to a struct, but the return value will be a
373 /// first-class struct value.
374 LLValue* DtoUnpaddedStruct(Type* dty, LLValue* v) {
375 assert(dty->ty == Tstruct);
376 TypeStruct* sty = (TypeStruct*) dty;
377 Array& fields = sty->sym->fields;
378
379 LLValue* newval = llvm::UndefValue::get(DtoUnpaddedStructType(dty));
380
381 for (unsigned i = 0; i < fields.dim; i++) {
382 VarDeclaration* vd = (VarDeclaration*) fields.data[i];
383 LLValue* fieldptr = DtoIndexStruct(v, sty->sym, vd);
384 LLValue* fieldval;
385 if (vd->type->ty == Tstruct) {
386 // Nested structs are the only members that can contain padding
387 fieldval = DtoUnpaddedStruct(vd->type, fieldptr);
388 } else {
389 fieldval = DtoLoad(fieldptr);
390 }
391 newval = DtoInsertValue(newval, fieldval, i);
392 }
393 return newval;
394 }
395
396 /// Undo the transformation performed by DtoUnpaddedStruct, writing to lval.
397 void DtoPaddedStruct(Type* dty, LLValue* v, LLValue* lval) {
398 assert(dty->ty == Tstruct);
399 TypeStruct* sty = (TypeStruct*) dty;
400 Array& fields = sty->sym->fields;
401
402 for (unsigned i = 0; i < fields.dim; i++) {
403 VarDeclaration* vd = (VarDeclaration*) fields.data[i];
404 LLValue* fieldptr = DtoIndexStruct(lval, sty->sym, vd);
405 LLValue* fieldval = DtoExtractValue(v, i);
406 if (vd->type->ty == Tstruct) {
407 // Nested structs are the only members that can contain padding
408 DtoPaddedStruct(vd->type, fieldval, fieldptr);
409 } else {
410 DtoStore(fieldval, fieldptr);
411 }
412 }
413 }