mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-06 10:57:35 +03:00
Respect alignments of captured variables when building nested context LL struct
This commit is contained in:
parent
05c10d9107
commit
93158caca8
7 changed files with 40 additions and 25 deletions
|
@ -16,6 +16,7 @@
|
||||||
#include "gen/logger.h"
|
#include "gen/logger.h"
|
||||||
#include "gen/tollvm.h"
|
#include "gen/tollvm.h"
|
||||||
#include "ir/irfunction.h"
|
#include "ir/irfunction.h"
|
||||||
|
#include "ir/irtypeaggr.h"
|
||||||
#include "llvm/Analysis/ValueTracking.h"
|
#include "llvm/Analysis/ValueTracking.h"
|
||||||
|
|
||||||
/****************************************************************************************/
|
/****************************************************************************************/
|
||||||
|
@ -334,24 +335,17 @@ static void DtoCreateNestedContextType(FuncDeclaration* fd)
|
||||||
|
|
||||||
IF_LOG Logger::cout() << "Function " << fd->toChars() << " has depth " << depth << '\n';
|
IF_LOG Logger::cout() << "Function " << fd->toChars() << " has depth " << depth << '\n';
|
||||||
|
|
||||||
typedef std::vector<LLType*> TypeVec;
|
AggrTypeBuilder builder(false);
|
||||||
TypeVec types;
|
|
||||||
if (depth != 0)
|
if (depth != 0)
|
||||||
{
|
{
|
||||||
assert(innerFrameType);
|
assert(innerFrameType);
|
||||||
|
unsigned ptrSize = gDataLayout->getPointerSize();
|
||||||
// Add frame pointer types for all but last frame
|
// Add frame pointer types for all but last frame
|
||||||
for (unsigned i = 0; i < (depth - 1); ++i)
|
for (unsigned i = 0; i < (depth - 1); ++i)
|
||||||
types.push_back(innerFrameType->getElementType(i));
|
builder.addType(innerFrameType->getElementType(i), ptrSize);
|
||||||
// Add frame pointer type for last frame
|
// Add frame pointer type for last frame
|
||||||
types.push_back(LLPointerType::getUnqual(innerFrameType));
|
builder.addType(LLPointerType::getUnqual(innerFrameType), ptrSize);
|
||||||
}
|
|
||||||
|
|
||||||
if (Logger::enabled() && depth != 0)
|
|
||||||
{
|
|
||||||
Logger::println("Frame types: ");
|
|
||||||
LOG_SCOPE;
|
|
||||||
for (TypeVec::iterator i = types.begin(); i != types.end(); ++i)
|
|
||||||
Logger::cout() << **i << '\n';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the direct nested variables of this function, and update their indices to match.
|
// Add the direct nested variables of this function, and update their indices to match.
|
||||||
|
@ -361,10 +355,16 @@ static void DtoCreateNestedContextType(FuncDeclaration* fd)
|
||||||
I != E; ++I)
|
I != E; ++I)
|
||||||
{
|
{
|
||||||
VarDeclaration* vd = *I;
|
VarDeclaration* vd = *I;
|
||||||
|
|
||||||
|
unsigned alignment = DtoAlignment(vd);
|
||||||
|
if (alignment > 1)
|
||||||
|
builder.alignCurrentOffset(alignment);
|
||||||
|
|
||||||
IrLocal& irLocal = *getIrLocal(vd, true);
|
IrLocal& irLocal = *getIrLocal(vd, true);
|
||||||
irLocal.nestedIndex = types.size();
|
irLocal.nestedIndex = builder.currentFieldIndex();
|
||||||
irLocal.nestedDepth = depth;
|
irLocal.nestedDepth = depth;
|
||||||
|
|
||||||
|
LLType* t = NULL;
|
||||||
if (vd->isParameter() && getIrParameter(vd)->arg)
|
if (vd->isParameter() && getIrParameter(vd)->arg)
|
||||||
{
|
{
|
||||||
// Parameters that are part of the LLVM signature will have
|
// Parameters that are part of the LLVM signature will have
|
||||||
|
@ -380,29 +380,32 @@ static void DtoCreateNestedContextType(FuncDeclaration* fd)
|
||||||
{
|
{
|
||||||
// This will be copied to the nesting frame.
|
// This will be copied to the nesting frame.
|
||||||
if (lazy)
|
if (lazy)
|
||||||
types.push_back(irparam->value->getType()->getContainedType(0));
|
t = irparam->value->getType()->getContainedType(0);
|
||||||
else
|
else
|
||||||
types.push_back(DtoMemType(vd->type));
|
t = DtoMemType(vd->type);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
types.push_back(irparam->value->getType());
|
t = irparam->value->getType();
|
||||||
}
|
}
|
||||||
else if (isSpecialRefVar(vd))
|
else if (isSpecialRefVar(vd))
|
||||||
types.push_back(DtoType(vd->type->pointerTo()));
|
t = DtoType(vd->type->pointerTo());
|
||||||
else
|
else
|
||||||
types.push_back(DtoMemType(vd->type));
|
t = DtoMemType(vd->type);
|
||||||
|
|
||||||
|
builder.addType(t, getTypeAllocSize(t));
|
||||||
|
|
||||||
IF_LOG Logger::cout() << "Nested var '" << vd->toChars()
|
IF_LOG Logger::cout() << "Nested var '" << vd->toChars()
|
||||||
<< "' of type " << *types.back() << "\n";
|
<< "' of type " << *t << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
LLStructType* frameType = LLStructType::create(gIR->context(), types,
|
LLStructType* frameType = LLStructType::create(gIR->context(), builder.defaultTypes(),
|
||||||
std::string("nest.") + fd->toChars());
|
std::string("nest.") + fd->toChars());
|
||||||
|
|
||||||
IF_LOG Logger::cout() << "frameType = " << *frameType << '\n';
|
IF_LOG Logger::cout() << "frameType = " << *frameType << '\n';
|
||||||
|
|
||||||
// Store type in IrFunction
|
// Store type in IrFunction
|
||||||
irFunc.frameType = frameType;
|
irFunc.frameType = frameType;
|
||||||
|
irFunc.frameTypeAlignment = builder.overallAlignment();
|
||||||
}
|
}
|
||||||
else // no captured variables
|
else // no captured variables
|
||||||
{
|
{
|
||||||
|
@ -411,6 +414,7 @@ static void DtoCreateNestedContextType(FuncDeclaration* fd)
|
||||||
// Propagate context arg properties if the context arg is passed on unmodified.
|
// Propagate context arg properties if the context arg is passed on unmodified.
|
||||||
IrFunction& parentIrFunc = *getIrFunc(parentFunc);
|
IrFunction& parentIrFunc = *getIrFunc(parentFunc);
|
||||||
irFunc.frameType = parentIrFunc.frameType;
|
irFunc.frameType = parentIrFunc.frameType;
|
||||||
|
irFunc.frameTypeAlignment = parentIrFunc.frameTypeAlignment;
|
||||||
irFunc.depth = parentIrFunc.depth;
|
irFunc.depth = parentIrFunc.depth;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -430,13 +434,18 @@ void DtoCreateNestedContext(FuncDeclaration* fd) {
|
||||||
unsigned depth = irfunction->depth;
|
unsigned depth = irfunction->depth;
|
||||||
LLStructType *frameType = irfunction->frameType;
|
LLStructType *frameType = irfunction->frameType;
|
||||||
// Create frame for current function and append to frames list
|
// Create frame for current function and append to frames list
|
||||||
// FIXME: alignment ?
|
|
||||||
LLValue* frame = 0;
|
LLValue* frame = 0;
|
||||||
bool needsClosure = fd->needsClosure();
|
bool needsClosure = fd->needsClosure();
|
||||||
if (needsClosure)
|
if (needsClosure)
|
||||||
|
{
|
||||||
|
// FIXME: alignment ?
|
||||||
frame = DtoGcMalloc(fd->loc, frameType, ".frame");
|
frame = DtoGcMalloc(fd->loc, frameType, ".frame");
|
||||||
|
}
|
||||||
else
|
else
|
||||||
frame = DtoRawAlloca(frameType, 0, ".frame");
|
{
|
||||||
|
unsigned alignment = std::max(getABITypeAlign(frameType), irfunction->frameTypeAlignment);
|
||||||
|
frame = DtoRawAlloca(frameType, alignment, ".frame");
|
||||||
|
}
|
||||||
|
|
||||||
// copy parent frames into beginning
|
// copy parent frames into beginning
|
||||||
if (depth != 0) {
|
if (depth != 0) {
|
||||||
|
|
|
@ -723,7 +723,7 @@ size_t getTypeAllocSize(LLType* t)
|
||||||
return gDataLayout->getTypeAllocSize(t);
|
return gDataLayout->getTypeAllocSize(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char getABITypeAlign(LLType* t)
|
unsigned int getABITypeAlign(LLType* t)
|
||||||
{
|
{
|
||||||
return gDataLayout->getABITypeAlignment(t);
|
return gDataLayout->getABITypeAlignment(t);
|
||||||
}
|
}
|
||||||
|
|
|
@ -131,7 +131,7 @@ size_t getTypePaddedSize(LLType* t);
|
||||||
size_t getTypeAllocSize(LLType* t);
|
size_t getTypeAllocSize(LLType* t);
|
||||||
|
|
||||||
// type alignments
|
// type alignments
|
||||||
unsigned char getABITypeAlign(LLType* t);
|
unsigned int getABITypeAlign(LLType* t);
|
||||||
|
|
||||||
// pair type helpers
|
// pair type helpers
|
||||||
LLValue* DtoAggrPair(LLType* type, LLValue* V1, LLValue* V2, const char* name = "");
|
LLValue* DtoAggrPair(LLType* type, LLValue* V1, LLValue* V2, const char* name = "");
|
||||||
|
|
|
@ -423,6 +423,7 @@ IrFunction::IrFunction(FuncDeclaration* fd) {
|
||||||
|
|
||||||
nestedVar = NULL;
|
nestedVar = NULL;
|
||||||
frameType = NULL;
|
frameType = NULL;
|
||||||
|
frameTypeAlignment = 0;
|
||||||
depth = -1;
|
depth = -1;
|
||||||
nestedContextCreated = false;
|
nestedContextCreated = false;
|
||||||
|
|
||||||
|
|
|
@ -411,6 +411,7 @@ struct IrFunction {
|
||||||
|
|
||||||
llvm::Value* nestedVar; // alloca for the nested context of this function
|
llvm::Value* nestedVar; // alloca for the nested context of this function
|
||||||
llvm::StructType* frameType; // type of nested context
|
llvm::StructType* frameType; // type of nested context
|
||||||
|
unsigned frameTypeAlignment; // its alignment
|
||||||
// number of enclosing functions with variables accessed by nested functions
|
// number of enclosing functions with variables accessed by nested functions
|
||||||
// (-1 if neither this function nor any enclosing ones access variables from enclosing functions)
|
// (-1 if neither this function nor any enclosing ones access variables from enclosing functions)
|
||||||
int depth;
|
int depth;
|
||||||
|
|
|
@ -50,7 +50,7 @@ bool var_offset_sort_cb(const VarDeclaration* v1, const VarDeclaration* v2)
|
||||||
}
|
}
|
||||||
|
|
||||||
AggrTypeBuilder::AggrTypeBuilder(bool packed) :
|
AggrTypeBuilder::AggrTypeBuilder(bool packed) :
|
||||||
m_offset(0), m_fieldIndex(0), m_packed(packed)
|
m_offset(0), m_fieldIndex(0), m_overallAlignment(0), m_packed(packed)
|
||||||
{
|
{
|
||||||
m_defaultTypes.reserve(32);
|
m_defaultTypes.reserve(32);
|
||||||
}
|
}
|
||||||
|
@ -192,6 +192,8 @@ void AggrTypeBuilder::addAggregate(AggregateDeclaration *ad)
|
||||||
|
|
||||||
void AggrTypeBuilder::alignCurrentOffset(unsigned alignment)
|
void AggrTypeBuilder::alignCurrentOffset(unsigned alignment)
|
||||||
{
|
{
|
||||||
|
m_overallAlignment = std::max(alignment, m_overallAlignment);
|
||||||
|
|
||||||
unsigned aligned = (m_offset + alignment - 1) & ~(alignment - 1);
|
unsigned aligned = (m_offset + alignment - 1) & ~(alignment - 1);
|
||||||
if (m_offset < aligned) {
|
if (m_offset < aligned) {
|
||||||
m_fieldIndex += add_zeros(m_defaultTypes, m_offset, aligned);
|
m_fieldIndex += add_zeros(m_defaultTypes, m_offset, aligned);
|
||||||
|
|
|
@ -43,11 +43,13 @@ public:
|
||||||
unsigned currentFieldIndex() const { return m_fieldIndex; }
|
unsigned currentFieldIndex() const { return m_fieldIndex; }
|
||||||
std::vector<llvm::Type*> defaultTypes() const { return m_defaultTypes; }
|
std::vector<llvm::Type*> defaultTypes() const { return m_defaultTypes; }
|
||||||
VarGEPIndices varGEPIndices() const { return m_varGEPIndices; }
|
VarGEPIndices varGEPIndices() const { return m_varGEPIndices; }
|
||||||
|
unsigned overallAlignment() const { return m_overallAlignment; }
|
||||||
protected:
|
protected:
|
||||||
std::vector<llvm::Type*> m_defaultTypes;
|
std::vector<llvm::Type*> m_defaultTypes;
|
||||||
VarGEPIndices m_varGEPIndices;
|
VarGEPIndices m_varGEPIndices;
|
||||||
unsigned m_offset;
|
unsigned m_offset;
|
||||||
unsigned m_fieldIndex;
|
unsigned m_fieldIndex;
|
||||||
|
unsigned m_overallAlignment;
|
||||||
bool m_packed;
|
bool m_packed;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue