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