Fixes for closures

This commit is contained in:
Alexey Prokhin
2010-12-15 17:05:16 +03:00
parent 73c851762b
commit 71f653f19b
7 changed files with 62 additions and 12 deletions

View File

@@ -772,6 +772,9 @@ void DtoDefineFunction(FuncDeclaration* fd)
}
#endif
FuncGen fg;
irfunction->gen = &fg;
DtoCreateNestedContext(fd);
#if DMDV2
@@ -801,12 +804,8 @@ void DtoDefineFunction(FuncDeclaration* fd)
}
// output function body
{
FuncGen fg;
irfunction->gen = &fg;
fd->fbody->toIR(gIR);
irfunction->gen = 0;
}
fd->fbody->toIR(gIR);
irfunction->gen = 0;
// TODO: clean up this mess

View File

@@ -130,6 +130,17 @@ llvm::AllocaInst* DtoRawAlloca(const llvm::Type* lltype, size_t alignment, const
return ai;
}
LLValue* DtoGcMalloc(const llvm::Type* lltype, const char* name)
{
// get runtime function
llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_allocmemory");
// parameters
LLValue *size = DtoConstSize_t(getTypeAllocSize(lltype));
// call runtime allocator
LLValue* mem = gIR->CreateCallOrInvoke(fn, size, name).getInstruction();
// cast
return DtoBitCast(mem, getPtrToType(lltype), name);
}
/****************************************************************************************/
/*////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -45,6 +45,7 @@ void DtoDeleteArray(DValue* arr);
llvm::AllocaInst* DtoAlloca(Type* type, const char* name = "");
llvm::AllocaInst* DtoArrayAlloca(Type* type, unsigned arraysize, const char* name = "");
llvm::AllocaInst* DtoRawAlloca(const llvm::Type* lltype, size_t alignment, const char* name = "");
LLValue* DtoGcMalloc(const llvm::Type* lltype, const char* name = "");
// assertion generator
void DtoAssert(Module* M, Loc loc, DValue* msg);

View File

@@ -68,6 +68,24 @@ static FuncDeclaration* getParentFunc(Dsymbol* sym, bool stopOnStatic) {
return (parent ? parent->isFuncDeclaration() : NULL);
}
static void storeVariable(VarDeclaration *vd, LLValue *dst)
{
LLValue *value = vd->ir.irLocal->value;
#if DMDV2
int ty = vd->type->ty;
FuncDeclaration *fd = getParentFunc(vd, true);
assert(fd && "No parent function for nested variable?");
if (fd->needsClosure() && !vd->isRef() && (ty == Tstruct || ty == Tsarray) && isaPointer(value->getType())) {
// Copy structs and static arrays
LLValue *mem = DtoGcMalloc(DtoType(vd->type), ".gc_mem");
DtoAggrCopy(mem, value);
DtoAlignedStore(mem, dst);
} else
#endif
// Store the address into the frame
DtoAlignedStore(value, dst);
}
static void DtoCreateNestedContextType(FuncDeclaration* fd);
DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd, bool byref)
@@ -206,7 +224,7 @@ void DtoNestedInit(VarDeclaration* vd)
val = DtoAlignedLoad(val, (std::string(".frame.") + parentfunc->toChars()).c_str());
}
val = DtoGEPi(val, 0, vd->ir.irLocal->nestedIndex, vd->toChars());
DtoAlignedStore(vd->ir.irLocal->value, val);
storeVariable(vd, val);
} else {
// Already initialized in DtoCreateNestedContext
}
@@ -534,11 +552,15 @@ void DtoCreateNestedContext(FuncDeclaration* fd) {
unsigned depth = irfunction->depth;
const llvm::StructType *frameType = irfunction->frameType;
// Create frame for current function and append to frames list
// FIXME: For D2, this should be a gc_malloc (or similar) call, not alloca
// (Note that it'd also require more aggressive copying of
// by-value parameters instead of just alloca'd ones)
// FIXME: alignment ?
LLValue* frame = DtoRawAlloca(frameType, 0, ".frame");
LLValue* frame = 0;
#if DMDV2
if (fd->needsClosure())
frame = DtoGcMalloc(frameType, ".frame");
else
#endif
frame = DtoRawAlloca(frameType, 0, ".frame");
// copy parent frames into beginning
if (depth != 0) {
@@ -602,7 +624,7 @@ void DtoCreateNestedContext(FuncDeclaration* fd) {
// passed-in pointer (for 'ref' or 'out' parameters) or
// a pointer arg with byval attribute.
// Store the address into the frame and set the byref flag.
DtoAlignedStore(vd->ir.irLocal->value, gep);
storeVariable(vd, gep);
vd->ir.irLocal->byref = true;
}
} else if (vd->isRef() || vd->isOut()) {

View File

@@ -264,6 +264,17 @@ static void LLVM_D_BuildRuntimeModule()
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
// void* _d_allocmemory(size_t sz)
{
llvm::StringRef fname("_d_allocmemory");
std::vector<const LLType*> types;
types.push_back(sizeTy);
const llvm::FunctionType* fty = llvm::FunctionType::get(voidPtrTy, types, false);
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M)
->setAttributes(Attr_NoAlias);
}
// void* _d_allocmemoryT(TypeInfo ti)
{
llvm::StringRef fname("_d_allocmemoryT");

View File

@@ -778,6 +778,11 @@ size_t getTypePaddedSize(const LLType* t)
return sz;
}
size_t getTypeAllocSize(const LLType* t)
{
return gTargetData->getTypeAllocSize(t);
}
unsigned char getABITypeAlign(const LLType* t)
{
return gTargetData->getABITypeAlignment(t);

View File

@@ -95,6 +95,7 @@ LLConstant* getNullValue(const LLType* t);
size_t getTypeBitSize(const LLType* t);
size_t getTypeStoreSize(const LLType* t);
size_t getTypePaddedSize(const LLType* t);
size_t getTypeAllocSize(const LLType* t);
// type alignments
unsigned char getABITypeAlign(const LLType* t);