Skip to content

Commit

Permalink
Add emit/create_gctmp_gep for temporary variables. Also add comments …
Browse files Browse the repository at this point in the history
…for how the GC frame is created.
  • Loading branch information
yuyichao committed Jun 4, 2015
1 parent 01ab266 commit 3c90872
Showing 1 changed file with 41 additions and 9 deletions.
50 changes: 41 additions & 9 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1525,12 +1525,25 @@ static void simple_escape_analysis(jl_value_t *expr, bool esc, jl_codectx_t *ctx

// --- gc root utils ---

// ---- Get Element Pointer (GEP) instructions within the GC frame ----

// Emit GEP for the @slot-th slot in the GC frame
static Value*
emit_gcgep(int slot, jl_codectx_t *ctx)
{
return builder.CreateConstGEP1_32(ctx->gc.argTemp, slot);
}

// Emit GEP for the @slot-th temporary variable in the GC frame.
// The temporary variables are after all local variables in the GC frame.
static Value*
emit_gctmp_gep(int slot, jl_codectx_t *ctx)
{
return emit_gcgep(slot + ctx->gc.argSpaceOffs, ctx);
}

// Create a GEP instruction for the @slot-th slot in the GC frame.
// (without inserting it)
static Instruction*
create_gcgep(int slot, jl_codectx_t *ctx)
{
Expand All @@ -1546,12 +1559,21 @@ create_gcgep(int slot, jl_codectx_t *ctx)
return ins;
}

// Create a GEP instruction for the @slot-th temporary variable in the
// GC frame. (without inserting it)
// The temporary variables are after all local variables in the GC frame.
static Instruction*
create_gctmp_gep(int slot, jl_codectx_t *ctx)
{
return create_gcgep(slot + ctx->gc.argSpaceOffs, ctx);
}

static Value *make_gcroot(Value *v, jl_codectx_t *ctx, jl_sym_t *var)
{
uint64_t slot = ctx->gc.argSpaceOffs + ctx->gc.argDepth;
Value *froot = emit_gcgep(slot, ctx);
Value *froot = emit_gctmp_gep(ctx->gc.argDepth, ctx);
builder.CreateStore(v, froot);
#ifdef LLVM36
uint64_t slot = ctx->gc.argSpaceOffs + ctx->gc.argDepth;
if (var != NULL) {
std::map<jl_sym_t *, jl_varinfo_t>::iterator it = ctx->vars.find(var);
if (it != ctx->vars.end() && ((llvm::MDNode*)it->second.dinfo) != NULL) {
Expand Down Expand Up @@ -1820,7 +1842,7 @@ static Value *emit_getfield(jl_value_t *expr, jl_sym_t *name, jl_codectx_t *ctx)
make_gcroot(arg1, ctx);
Value *arg2 = literal_pointer_val((jl_value_t*)name);
make_gcroot(arg2, ctx);
Value *myargs = emit_gcgep(argStart + ctx->gc.argSpaceOffs, ctx);
Value *myargs = emit_gctmp_gep(argStart, ctx);
#ifdef LLVM37
Value *result = builder.CreateCall(prepare_call(jlgetfield_func), {V_null, myargs,
ConstantInt::get(T_int32,2)});
Expand Down Expand Up @@ -2430,7 +2452,7 @@ static Value *emit_jlcall(Value *theFptr, Value *theF, int argStart,
// call
Value *myargs = Constant::getNullValue(jl_ppvalue_llvmt);
if (ctx->gc.argTemp != NULL && nargs > 0) {
myargs = emit_gcgep(argStart + ctx->gc.argSpaceOffs, ctx);
myargs = emit_gctmp_gep(argStart, ctx);
}
#ifdef LLVM37
Value *result = builder.CreateCall(prepare_call(theFptr), {theF, myargs,
Expand Down Expand Up @@ -2621,7 +2643,7 @@ static Value *emit_call(jl_value_t **args, size_t arglen, jl_codectx_t *ctx, jl_
// is function
Value *myargs = Constant::getNullValue(jl_ppvalue_llvmt);
if (ctx->gc.argTemp != NULL && nargs > 0) {
myargs = emit_gcgep(argStart + 1 + ctx->gc.argSpaceOffs, ctx);
myargs = emit_gctmp_gep(argStart + 1, ctx);
}
theFptr = emit_nthptr_recast(theFunc, (ssize_t)(offsetof(jl_function_t,fptr)/sizeof(void*)), tbaa_func, jl_pfptr_llvmt);
#ifdef LLVM37
Expand All @@ -2635,7 +2657,7 @@ static Value *emit_call(jl_value_t **args, size_t arglen, jl_codectx_t *ctx, jl_
ctx->f->getBasicBlockList().push_back(elseBB1);
builder.SetInsertPoint(elseBB1);
// not function
myargs = emit_gcgep(argStart + ctx->gc.argSpaceOffs, ctx);
myargs = emit_gctmp_gep(argStart, ctx);
#ifdef LLVM37
Value *r2 = builder.CreateCall(prepare_call(jlapplygeneric_func),
{literal_pointer_val((jl_value_t*)jl_module_call_func(ctx->module)),
Expand Down Expand Up @@ -3420,6 +3442,8 @@ static void allocate_gc_frame(size_t n_roots, BasicBlock *b0, jl_codectx_t *ctx)

#ifdef JL_GC_MARKSWEEP
// allocate gc frame
// gc->gcframe is assumed to be the first instruction creating the gc frame
// in finalize_gc_frame
gc->gcframe = (Instruction*)builder.CreateAlloca(
jl_pvalue_llvmt, ConstantInt::get(T_int32, n_roots + 2));
gc->argTemp = (Instruction*)builder.CreateConstGEP1_32(gc->gcframe, 2);
Expand All @@ -3430,6 +3454,8 @@ static void allocate_gc_frame(size_t n_roots, BasicBlock *b0, jl_codectx_t *ctx)
builder.CreateBitCast(builder.CreateConstGEP1_32(gc->gcframe, 1), PointerType::get(jl_ppvalue_llvmt,0)));
Instruction *linst = builder.CreateStore(gc->gcframe, prepare_global(jlpgcstack_var), false);
#else
// gc->gcframe is assumed to be the first instruction creating the gc frame
// in finalize_gc_frame
gc->argTemp = builder.CreateAlloca(jl_pvalue_llvmt,
ConstantInt::get(T_int32, n_roots));
gc->gcframe = gc->argTemp;
Expand Down Expand Up @@ -3468,11 +3494,15 @@ static void clear_gc_frame(jl_gcinfo_t *gc)
}
}

// Remove GC frame creation
// (instructions from gc->gcframe to gc->last_gcframe_inst)
BasicBlock::InstListType &il = gc->gcframe->getParent()->getInstList();
il.erase(BasicBlock::iterator(gc->gcframe), last_gcframe_inst);
// erase() erases up *to* the end point; erase last inst too
il.erase(last_gcframe_inst);
for(size_t i=0; i < gc->gc_frame_pops.size(); i++) {
// Remove GC pops
// (4 instructions from each element in the gc->gc_frame_pops)
for (size_t i=0; i < gc->gc_frame_pops.size(); i++) {
Instruction *pop = gc->gc_frame_pops[i];
BasicBlock::InstListType &il2 = pop->getParent()->getInstList();
BasicBlock::iterator pi(pop);
Expand All @@ -3492,6 +3522,7 @@ static void finalize_gc_frame(jl_codectx_t *ctx)
}
else {
// n_frames++;
// Fix the size of the GC frame created
BasicBlock::iterator bbi(gc->gcframe);
AllocaInst *newgcframe =
new AllocaInst(jl_pvalue_llvmt,
Expand All @@ -3513,9 +3544,9 @@ static void finalize_gc_frame(jl_codectx_t *ctx)
Instruction *after = gc->last_gcframe_inst;
BasicBlock::InstListType &instList = after->getParent()->getInstList();

// Initialize the slots for temporary variables to NULL
for (int i = 0;i < gc->maxDepth;i++) {
int offset = i + gc->argSpaceOffs;
Instruction *argTempi = create_gcgep(offset, ctx);
Instruction *argTempi = create_gctmp_gep(i, ctx);
instList.insertAfter(after, argTempi);
after = new StoreInst(V_null, argTempi);
instList.insertAfter(argTempi, after);
Expand All @@ -3539,6 +3570,7 @@ static void
emit_gcpop(jl_codectx_t *ctx)
{
#ifdef JL_GC_MARKSWEEP
// finalize_gc_frame assumes each frame pop takes 4 instructions.
Instruction *gcpop =
(Instruction*)builder.CreateConstGEP1_32(ctx->gc.gcframe, 1);
ctx->gc.gc_frame_pops.push_back(gcpop);
Expand Down

0 comments on commit 3c90872

Please sign in to comment.