Skip to content

Commit

Permalink
Support GC closures with alignment > 16
Browse files Browse the repository at this point in the history
Tested by tests/dmd/runnable/test16098.d.
  • Loading branch information
kinke committed Feb 19, 2023
1 parent 56785d4 commit ef8ba48
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 17 deletions.
11 changes: 0 additions & 11 deletions gen/llvmhelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -207,17 +207,6 @@ llvm::AllocaInst *DtoRawAlloca(LLType *lltype, size_t alignment,
return ai;
}

LLValue *DtoGcMalloc(const Loc &loc, LLType *lltype, const char *name) {
// get runtime function
llvm::Function *fn = getRuntimeFunction(loc, gIR->module, "_d_allocmemory");
// parameters
LLValue *size = DtoConstSize_t(getTypeAllocSize(lltype));
// call runtime allocator
LLValue *mem = gIR->CreateCallOrInvoke(fn, size, name);
// cast
return DtoBitCast(mem, getPtrToType(lltype), name);
}

LLValue *DtoAllocaDump(DValue *val, const char *name) {
return DtoAllocaDump(val, val->type, name);
}
Expand Down
1 change: 0 additions & 1 deletion gen/llvmhelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ llvm::AllocaInst *DtoArrayAlloca(Type *type, unsigned arraysize,
const char *name = "");
llvm::AllocaInst *DtoRawAlloca(LLType *lltype, size_t alignment,
const char *name = "");
LLValue *DtoGcMalloc(const Loc &loc, LLType *lltype, const char *name = "");

LLValue *DtoAllocaDump(DValue *val, const char *name = "");
LLValue *DtoAllocaDump(DValue *val, int alignment, const char *name = "");
Expand Down
27 changes: 22 additions & 5 deletions gen/nested.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "gen/irstate.h"
#include "gen/llvmhelpers.h"
#include "gen/logger.h"
#include "gen/runtime.h"
#include "gen/tollvm.h"
#include "ir/irfunction.h"
#include "ir/irtypeaggr.h"
Expand Down Expand Up @@ -488,17 +489,33 @@ void DtoCreateNestedContext(FuncGenState &funcGen) {
auto &irFunc = funcGen.irFunc;
unsigned depth = irFunc.depth;
LLStructType *frameType = irFunc.frameType;
const unsigned frameAlignment =
std::max(getABITypeAlign(frameType), irFunc.frameTypeAlignment);

// Create frame for current function and append to frames list
LLValue *frame = nullptr;
bool needsClosure = fd->needsClosure();
IF_LOG Logger::println("Needs closure (GC) flag: %d", (int)needsClosure);
if (needsClosure) {
// FIXME: alignment ?
frame = DtoGcMalloc(fd->loc, frameType, ".frame");
LLFunction *fn =
getRuntimeFunction(fd->loc, gIR->module, "_d_allocmemory");
auto size = getTypeAllocSize(frameType);
if (frameAlignment > 16) // GC guarantees an alignment of 16
size += frameAlignment - 16;
LLValue *mem =
gIR->CreateCallOrInvoke(fn, DtoConstSize_t(size), ".gc_frame");
if (frameAlignment <= 16) {
frame = DtoBitCast(mem, frameType->getPointerTo(), ".frame");
} else {
const uint64_t mask = frameAlignment - 1;
mem = gIR->ir->CreatePtrToInt(mem, DtoSize_t());
mem = gIR->ir->CreateAdd(mem, DtoConstSize_t(mask));
mem = gIR->ir->CreateAnd(mem, DtoConstSize_t(~mask));
frame =
gIR->ir->CreateIntToPtr(mem, frameType->getPointerTo(), ".frame");
}
} else {
unsigned alignment =
std::max(getABITypeAlign(frameType), irFunc.frameTypeAlignment);
frame = DtoRawAlloca(frameType, alignment, ".frame");
frame = DtoRawAlloca(frameType, frameAlignment, ".frame");
}

// copy parent frames into beginning
Expand Down

0 comments on commit ef8ba48

Please sign in to comment.