diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index 72f06f92dc..dd0400eab9 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -1440,3 +1440,40 @@ IrModule * getIrModule(Module * M) } ////////////////////////////////////////////////////////////////////////////////////////// + +size_t realignOffset(size_t offset, Type* type) +{ + size_t alignsize = type->alignsize(); + size_t alignedoffset = (offset + alignsize - 1) & ~(alignsize - 1); + + // if the aligned offset already matches the input offset + // don't waste time checking things are ok! + if (alignedoffset == offset) + return alignedoffset; + + // disabled since this can fail for opaques. if the check above is not in place + // it does so for gcx.d!!! + // this needs to be investigated, but I don't have time right now! +#if 0 + // if not, we have to make sure it agrees with what llvm thinks is the alignment + // sometimes this is different from what we really need (in case of unions, see #294) + // so if there we get different results we don't realign the offset at all and instead + // just return the original offset, and rely on the users to insert padding manually. + IF_LOG Logger::cout() << "getting alignment for type " << type->toChars() + << " with llvm type " << *DtoType(type) << std::endl; + size_t alignsize2 = gTargetData->getABITypeAlignment(DtoType(type)); + + if (alignsize != alignsize2) + { + assert(alignsize > alignsize2 && "this is not good, the D and LLVM " + "type alignments differ, but LLVM's is bigger! This will break " + "the type mapping algorithms"); + // don't try and align the offset, and let the mappers pad 100% manually + return offset; + } +#endif + + return alignedoffset; +} + +////////////////////////////////////////////////////////////////////////////////////////// diff --git a/gen/llvmhelpers.h b/gen/llvmhelpers.h index 8cc4e38cbd..391fe820b6 100644 --- a/gen/llvmhelpers.h +++ b/gen/llvmhelpers.h @@ -141,6 +141,10 @@ DValue* DtoInlineAsmExpr(Loc loc, FuncDeclaration* fd, Expressions* arguments); /// Create the IrModule if necessary and returns it. IrModule* getIrModule(Module* M); +/// Update an offset to make sure it follows both the D and LLVM alignments. +/// Returns the offset rounded up to the closest safely aligned offset. +size_t realignOffset(size_t offset, Type* type); + //////////////////////////////////////////// // gen/tocall.cpp stuff below //////////////////////////////////////////// diff --git a/gen/toir.cpp b/gen/toir.cpp index 6750475f45..66f152cf1c 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -2459,8 +2459,7 @@ DValue* StructLiteralExp::toElem(IRState* p) size_t alignedoffset = offset; if (!packed) { - size_t alignsize = vd->type->alignsize(); - alignedoffset = (offset + alignsize - 1) & ~(alignsize - 1); + alignedoffset = realignOffset(alignedoffset, vd->type); } // insert explicit padding? diff --git a/ir/irclass.cpp b/ir/irclass.cpp index 624b06cfd9..8754744ee5 100644 --- a/ir/irclass.cpp +++ b/ir/irclass.cpp @@ -222,8 +222,7 @@ void IrStruct::addBaseClassInits( assert(vd->offset >= offset && "default fields not sorted by offset"); // get next aligned offset for this type - size_t alignsize = vd->type->alignsize(); - size_t alignedoffset = (offset + alignsize - 1) & ~(alignsize - 1); + size_t alignedoffset = realignOffset(offset, vd->type); // insert explicit padding? if (alignedoffset < vd->offset) diff --git a/ir/irstruct.cpp b/ir/irstruct.cpp index 144bad19d9..b058596c70 100644 --- a/ir/irstruct.cpp +++ b/ir/irstruct.cpp @@ -169,8 +169,7 @@ LLConstant * IrStruct::createStructDefaultInitializer() size_t alignedoffset = offset; if (!packed) { - size_t alignsize = vd->type->alignsize(); - alignedoffset = (offset + alignsize - 1) & ~(alignsize - 1); + alignedoffset = realignOffset(alignedoffset, vd->type); } // insert explicit padding? @@ -355,8 +354,7 @@ LLConstant * IrStruct::createStructInitializer(StructInitializer * si) size_t alignedoffset = offset; if (!packed) { - size_t alignsize = vd->type->alignsize(); - alignedoffset = (offset + alignsize - 1) & ~(alignsize - 1); + alignedoffset = realignOffset(alignedoffset, vd->type); } // insert explicit padding? diff --git a/ir/irtypeclass.cpp b/ir/irtypeclass.cpp index 3bc9bf4a98..4ae835e8ee 100644 --- a/ir/irtypeclass.cpp +++ b/ir/irtypeclass.cpp @@ -9,6 +9,7 @@ #include "gen/logger.h" #include "gen/tollvm.h" #include "gen/utils.h" +#include "gen/llvmhelpers.h" #include "ir/irtypeclass.h" ////////////////////////////////////////////////////////////////////////////// @@ -143,8 +144,7 @@ void IrTypeClass::addBaseClassData( default_fields.push_back(vd); // get next aligned offset for this type - size_t alignsize = vd->type->alignsize(); - size_t alignedoffset = (offset + alignsize - 1) & ~(alignsize - 1); + size_t alignedoffset = realignOffset(offset, vd->type); // insert explicit padding? if (alignedoffset < vd->offset) diff --git a/ir/irtypestruct.cpp b/ir/irtypestruct.cpp index 9b08d4fae6..f5d9bf8c06 100644 --- a/ir/irtypestruct.cpp +++ b/ir/irtypestruct.cpp @@ -8,6 +8,7 @@ #include "gen/tollvm.h" #include "gen/logger.h" #include "gen/utils.h" +#include "gen/llvmhelpers.h" #include "ir/irtypestruct.h" ////////////////////////////////////////////////////////////////////////////// @@ -192,8 +193,7 @@ const llvm::Type* IrTypeStruct::buildType() size_t alignedoffset = offset; if (!packed) { - size_t alignsize = vd->type->alignsize(); - alignedoffset = (offset + alignsize - 1) & ~(alignsize - 1); + alignedoffset = realignOffset(alignedoffset, vd->type); } // insert explicit padding?