Skip to content

Commit

Permalink
Import Debug Info changes
Browse files Browse the repository at this point in the history
  • Loading branch information
Keno committed Feb 3, 2015
1 parent 881719b commit b75922b
Show file tree
Hide file tree
Showing 6 changed files with 202 additions and 28 deletions.
1 change: 1 addition & 0 deletions src/alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -718,6 +718,7 @@ jl_datatype_t *jl_new_datatype(jl_sym_t *name, jl_datatype_t *super,
t->ninitialized = ninitialized;
t->instance = NULL;
t->struct_decl = NULL;
t->ditype = NULL;
t->size = 0;
t->alignment = 1;

Expand Down
17 changes: 17 additions & 0 deletions src/cgutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,23 @@ class FunctionMover : public ValueMaterializer
};
#endif

static DIType julia_type_to_di(jl_value_t *jt, DIBuilder *dbuilder, bool isboxed = false)
{
if (jl_is_abstracttype(jt) || !jl_is_datatype(jt) || !jl_isbits(jt) || isboxed)
return jl_pvalue_dillvmt;
jl_datatype_t *jdt = (jl_datatype_t*)jt;
if (jdt->ditype != NULL)
return DIType((llvm::MDNode*)jdt->ditype);
if (jl_is_bitstype(jt)) {
DIType t = dbuilder->createBasicType(jdt->name->name->name,jdt->size,jdt->alignment,llvm::dwarf::DW_ATE_unsigned);
MDNode *M = t;
jdt->ditype = M;
return t;
}
// TODO: Fixme
return jl_pvalue_dillvmt;
}

// --- emitting pointers directly into code ---

static Value *literal_static_pointer_val(void *p, Type *t)
Expand Down
209 changes: 181 additions & 28 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,16 @@ namespace llvm {
extern bool annotateSimdLoop( BasicBlock* latch );
}

// Basic DITypes
static DICompositeType jl_value_dillvmt;
static DIDerivedType jl_pvalue_dillvmt;
static DIDerivedType jl_ppvalue_dillvmt;
#ifdef LLVM36
DISubroutineType jl_di_func_sig;
#else
DICompositeType jl_di_func_sig;
#endif

// constants
static Value *V_null;

Expand Down Expand Up @@ -340,6 +350,7 @@ struct jl_varinfo_t {
Value *memvalue; // an address, if the var is alloca'd
Value *SAvalue; // register, if the var is SSA
Value *passedAs; // if an argument, the original passed value
DIVariable dinfo;
int closureidx; // index in closure env, or -1
bool isAssigned;
bool isCaptured;
Expand All @@ -354,10 +365,10 @@ struct jl_varinfo_t {
jl_value_t *declType;
jl_value_t *initExpr; // initializing expression for SSA variables

jl_varinfo_t() : memvalue(NULL), SAvalue(NULL), passedAs(NULL), closureidx(-1),
isAssigned(true), isCaptured(false), isSA(false), isVolatile(false),
isArgument(false), isGhost(false), hasGCRoot(false), escapes(true),
usedUndef(false), used(false),
jl_varinfo_t() : memvalue(NULL), SAvalue(NULL), passedAs(NULL), dinfo(DIVariable()),
closureidx(-1), isAssigned(true), isCaptured(false), isSA(false),
isVolatile(false), isArgument(false), isGhost(false), hasGCRoot(false),
escapes(true), usedUndef(false), used(false),
declType((jl_value_t*)jl_any_type), initExpr(NULL)
{
}
Expand Down Expand Up @@ -511,15 +522,17 @@ typedef struct {
BasicBlock::iterator first_gcframe_inst;
BasicBlock::iterator last_gcframe_inst;
llvm::DIBuilder *dbuilder;
bool debug_enabled;
std::vector<Instruction*> gc_frame_pops;
std::vector<CallInst*> to_inline;
} jl_codectx_t;

static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool boxed=true,
bool valuepos=true);
bool valuepos=true, jl_sym_t **valuevar=NULL);
static Value *emit_unboxed(jl_value_t *e, jl_codectx_t *ctx);
static int is_global(jl_sym_t *s, jl_codectx_t *ctx);
static Value *make_gcroot(Value *v, jl_codectx_t *ctx);

static Value *make_gcroot(Value *v, jl_codectx_t *ctx, jl_sym_t *var = NULL);
static Value *emit_boxed_rooted(jl_value_t *e, jl_codectx_t *ctx);
static Value *global_binding_pointer(jl_module_t *m, jl_sym_t *s,
jl_binding_t **pbnd, bool assign);
Expand Down Expand Up @@ -629,7 +642,7 @@ static Function *to_function(jl_lambda_info_t *li, bool cstyle)

static void jl_setup_module(Module *m, bool add)
{
m->addModuleFlag(llvm::Module::Warning, "Dwarf Version",3);
m->addModuleFlag(llvm::Module::Warning, "Dwarf Version",2);
#ifdef LLVM34
m->addModuleFlag(llvm::Module::Error, "Debug Info Version",
llvm::DEBUG_METADATA_VERSION);
Expand Down Expand Up @@ -1362,13 +1375,27 @@ static void simple_escape_analysis(jl_value_t *expr, bool esc, jl_codectx_t *ctx

// --- gc root utils ---

static Value *make_gcroot(Value *v, jl_codectx_t *ctx)
static Value *make_gcroot(Value *v, jl_codectx_t *ctx, jl_sym_t *var)
{
uint64_t slot = ctx->argSpaceOffs + ctx->argDepth;
Value *froot = builder.CreateGEP(ctx->argTemp,
ConstantInt::get(T_size,
ctx->argSpaceOffs +
ctx->argDepth));
ConstantInt::get(T_size,slot));
builder.CreateStore(v, froot);
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)
{
if (ctx->debug_enabled) {
SmallVector<int64_t, 9> addr;
addr.push_back(llvm::dwarf::DW_OP_plus);
addr.push_back(slot * sizeof(void*));
addr.push_back(llvm::dwarf::DW_OP_deref);
ctx->dbuilder->insertDeclare(ctx->argTemp, it->second.dinfo,
ctx->dbuilder->createExpression(addr), builder.GetInsertBlock());
}
}
}
ctx->argDepth++;
if (ctx->argDepth > ctx->maxDepth)
ctx->maxDepth = ctx->argDepth;
Expand Down Expand Up @@ -2473,9 +2500,10 @@ static Value *emit_jlcall(Value *theFptr, Value *theF, jl_value_t **args,
// emit arguments
int argStart = ctx->argDepth;
for(size_t i=0; i < nargs; i++) {
Value *anArg = emit_expr(args[i], ctx);
jl_sym_t *sym = NULL;
Value *anArg = emit_expr(args[i], ctx, true, true, &sym);
// put into argument space
make_gcroot(boxed(anArg, ctx, expr_type(args[i],ctx)), ctx);
make_gcroot(boxed(anArg, ctx, expr_type(args[i],ctx)), ctx, sym);
}

// call
Expand Down Expand Up @@ -2916,6 +2944,8 @@ static void emit_assignment(jl_value_t *l, jl_value_t *r, jl_codectx_t *ctx)
builder.CreateCall2(prepare_call(jlcheckassign_func),
literal_pointer_val(bnd),
rval);
// Global variable. Does not need debug info because the debugger knows about
// it's memory location.
}
else {
jl_varinfo_t &vi = ctx->vars[s];
Expand Down Expand Up @@ -2958,15 +2988,21 @@ static Value *emit_condition(jl_value_t *cond, const std::string &msg, jl_codect
}

static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed,
bool valuepos)
bool valuepos, jl_sym_t **valuevar)
{
if (jl_is_symbol(expr)) {
if (!valuepos) return NULL;
return emit_var((jl_sym_t*)expr, (jl_value_t*)jl_undef_type, ctx, isboxed);
jl_sym_t *sym = (jl_sym_t*)expr;
if (valuevar != NULL)
*valuevar = sym;
return emit_var(sym, (jl_value_t*)jl_undef_type, ctx, isboxed);
}
if (jl_is_symbolnode(expr)) {
if (!valuepos) return NULL;
return emit_var(jl_symbolnode_sym(expr), jl_symbolnode_type(expr), ctx, isboxed);
jl_sym_t *sym = jl_symbolnode_sym(expr);
if (valuevar != NULL)
*valuevar = sym;
return emit_var(sym, jl_symbolnode_type(expr), ctx, isboxed);
}
if (jl_is_gensym(expr)) {
if (!valuepos) return NULL;
Expand Down Expand Up @@ -3428,6 +3464,8 @@ static Value *alloc_local(jl_sym_t *s, jl_codectx_t *ctx)
vi.isGhost = true;
}
vi.memvalue = lv;
if (!vi.isGhost && ctx->debug_enabled)
ctx->dbuilder->insertDeclare(lv,vi.dinfo,ctx->dbuilder->createExpression(),builder.GetInsertBlock());
return lv;
}

Expand Down Expand Up @@ -3904,20 +3942,15 @@ static Function *emit_function(jl_lambda_info_t *lam, bool cstyle)
BasicBlock *b0 = BasicBlock::Create(jl_LLVMContext, "top", f);
builder.SetInsertPoint(b0);

#ifdef LLVM36
llvm::DITypeArray EltTypeArray = dbuilder.getOrCreateTypeArray(None);
#else
llvm::DIArray EltTypeArray = dbuilder.getOrCreateArray(ArrayRef<Value*>());
#endif
//ios_printf(ios_stderr, "\n*** compiling %s at %s:%d\n\n",
// lam->name->name, filename.c_str(), lno);

DebugLoc noDbg;
bool debug_enabled = true;
ctx.debug_enabled = true;
if (dbgFuncName[0] == 0) {
// special value: if function name is empty, disable debug info
builder.SetCurrentDebugLocation(noDbg);
debug_enabled = false;
ctx.debug_enabled = false;
do_coverage = false;
do_malloc_log = false;
}
Expand All @@ -3930,11 +3963,33 @@ static Function *emit_function(jl_lambda_info_t *lam, bool cstyle)
assert(CU.Verify());
#endif


#ifdef LLVM36
DISubroutineType subrty;
#else
DICompositeType subrty;
#endif

if (!specsig) {
subrty = jl_di_func_sig;
} else {
#ifdef LLVM36
llvm::DITypeArray EltTypeArray;
#else
llvm::DIArray EltTypeArray;
#endif
std::vector<Value*> ditypes(0);
for(size_t i=0; i < jl_tuple_len(lam->specTypes); i++) {
if(ctx.vars[jl_decl_var(jl_cellref(largs,i))].isGhost)
continue;
ditypes.push_back(julia_type_to_di(jl_tupleref(lam->specTypes,i),ctx.dbuilder,false));
}
#ifdef LLVM36
DISubroutineType subrty = dbuilder.createSubroutineType(fil,EltTypeArray);
subrty = ctx.dbuilder->createSubroutineType(fil,ctx.dbuilder->getOrCreateTypeArray(ditypes));
#else
DICompositeType subrty = dbuilder.createSubroutineType(fil,EltTypeArray);
subrty = ctx.dbuilder->createSubroutineType(fil,ctx.dbuilder->getOrCreateArray(ditypes));
#endif
}

fil = dbuilder.createFile(filename, ".");
#ifndef LLVM34
Expand All @@ -3958,6 +4013,51 @@ static Function *emit_function(jl_lambda_info_t *lam, bool cstyle)
assert(SP.Verify() && SP.describes(f) && SP.getFunction() == f);
}

if (ctx.debug_enabled) {
// Go over all arguments and local variables and initialize their debug information
for(i=0; i < nreq; i++) {
jl_sym_t *argname = jl_decl_var(jl_cellref(largs,i));
jl_varinfo_t &varinfo = ctx.vars[argname];
varinfo.dinfo = ctx.dbuilder->createLocalVariable(
llvm::dwarf::DW_TAG_arg_variable, // Tag
SP, // Scope (current function will be fill in later)
argname->name, // Variable name
fil, // File
ctx.lineno, // Line (for now, use lineno of the function)
julia_type_to_di(varinfo.declType,ctx.dbuilder,specsig), // Variable type
false, // May be optimized out
0, // Flags (TODO: Do we need any)
i+1); // Argument number (1-based)

}
if (va) {
ctx.vars[ctx.vaName].dinfo = ctx.dbuilder->createLocalVariable(
llvm::dwarf::DW_TAG_arg_variable, // Tag
SP, // Scope (current function will be fill in later)
ctx.vaName->name, // Variable name
fil, // File
ctx.lineno, // Line (for now, use lineno of the function)
julia_type_to_di(ctx.vars[ctx.vaName].declType,ctx.dbuilder,false), // Variable type
false, // May be optimized out
0, // Flags (TODO: Do we need any)
nreq + 1); // Argument number (1-based)
}
for(i=0; i < lvarslen; i++) {
jl_sym_t *s = (jl_sym_t*)jl_cellref(lvars,i);
jl_varinfo_t &varinfo = ctx.vars[s];
varinfo.dinfo = ctx.dbuilder->createLocalVariable(
llvm::dwarf::DW_TAG_auto_variable, // Tag
SP, // Scope (current function will be fill in later)
s->name, // Variable name
fil, // File
ctx.lineno == -1 ? 0 : ctx.lineno, // Line (for now, use lineno of the function)
julia_type_to_di(varinfo.declType,ctx.dbuilder,specsig), // Variable type
false, // May be optimized out
0, // Flags (TODO: Do we need any)
0); // Argument number (1-based)
}
}

std::map<jl_sym_t *, MDNode *> filescopes;

Value *fArg=NULL, *argArray=NULL, *argCount=NULL;
Expand Down Expand Up @@ -4168,6 +4268,14 @@ static Function *emit_function(jl_lambda_info_t *lam, bool cstyle)
}
}
else {
if (ctx.vars[s].dinfo != NULL) {
SmallVector<int64_t, 9> addr;
addr.push_back(llvm::dwarf::DW_OP_plus);
addr.push_back(argIdx * sizeof(void*));
addr.push_back(llvm::dwarf::DW_OP_deref);
ctx.dbuilder->insertDbgValueIntrinsic(argArray, 0, ctx.vars[s].dinfo,
ctx.dbuilder->createExpression(addr), builder.GetInsertBlock());
}
argPtr = builder.CreateGEP(argArray, ConstantInt::get(T_size, argIdx));
argIdx++;
}
Expand Down Expand Up @@ -4276,7 +4384,7 @@ static Function *emit_function(jl_lambda_info_t *lam, bool cstyle)
jl_value_t *stmt = jl_cellref(stmts,i);
if (jl_is_linenode(stmt)) {
lno = jl_linenode_line(stmt);
if (debug_enabled)
if (ctx.debug_enabled)
builder.SetCurrentDebugLocation(DebugLoc::get(lno, 1, (MDNode*)SP, NULL));
if (do_coverage)
coverageVisitLine(filename, lno);
Expand All @@ -4301,7 +4409,7 @@ static Function *emit_function(jl_lambda_info_t *lam, bool cstyle)
}
}
}
if (debug_enabled) {
if (ctx.debug_enabled) {
MDNode *scope;
if (dfil == NULL)
scope = SP;
Expand Down Expand Up @@ -4385,7 +4493,7 @@ static Function *emit_function(jl_lambda_info_t *lam, bool cstyle)
}

// step 18. Perform any delayed instantiations
if (debug_enabled)
if (ctx.debug_enabled)
ctx.dbuilder->finalize();

JL_GC_POP();
Expand Down Expand Up @@ -4543,6 +4651,51 @@ static void init_julia_llvm_env(Module *m)
valueSt->setBody(vselts);
jl_value_llvmt = valueSt;


DIBuilder dbuilder(*m);
DIFile julia_h = dbuilder.createFile("julia.h","");

jl_value_dillvmt = dbuilder.createStructType(DIDescriptor(),
"jl_value_t",
julia_h,
71, // At the time of this writing. Not sure if it's worth it to keep this in sync
sizeof(jl_value_t)*8,
__alignof__(jl_value_t)*8,
0, // Flags
DIType(), // Derived from
DIArray()); // Elements - will be corrected later

jl_pvalue_dillvmt = dbuilder.createPointerType(jl_value_dillvmt,sizeof(jl_value_t*)*8,
__alignof__(jl_value_t*)*8);

DIArray types;
SmallVector<llvm::Value *, 1> Elts;
Elts.push_back(jl_pvalue_dillvmt);

#ifdef LLVM36
jl_value_dillvmt.setArrays(dbuilder.getOrCreateTypeArray(Elts));
#else
jl_value_dillvmt.setTypeArray(dbuilder.getOrCreateArray(Elts));
#endif

jl_ppvalue_dillvmt = dbuilder.createPointerType(jl_pvalue_dillvmt,sizeof(jl_value_t**)*8,
__alignof__(jl_value_t**)*8);

std::vector<Value*> diargs(0);
diargs.push_back(jl_pvalue_dillvmt); // Return Type (ret value)
diargs.push_back(jl_pvalue_dillvmt); // First Argument (function)
diargs.push_back(jl_ppvalue_dillvmt); // Second Argument (argv)
// Third argument (length(argv))
diargs.push_back(julia_type_to_di((jl_value_t*)jl_int32_type,&dbuilder,false));

#ifdef LLVM36
jl_di_func_sig = dbuilder.createSubroutineType(julia_h,
dbuilder.getOrCreateTypeArray(diargs));
#else
jl_di_func_sig = dbuilder.createSubroutineType(julia_h,
dbuilder.getOrCreateArray(diargs));
#endif

jl_pvalue_llvmt = PointerType::get(jl_value_llvmt, 0);
jl_ppvalue_llvmt = PointerType::get(jl_pvalue_llvmt, 0);
two_pvalue_llvmt.push_back(jl_pvalue_llvmt);
Expand Down
Loading

0 comments on commit b75922b

Please sign in to comment.