Skip to content

Commit

Permalink
fix a number of minor nits with inline line numbers
Browse files Browse the repository at this point in the history
* the inlining pass would discard the first LineNumberNode, without
  checking that it matched the line number of the function declaration

* the CurrentDebugLocation shouldn't be set while emitting the prologue

* implement inlining info for pre-MCJIT llvm

* improve printing of relative symbols in disassembly (e.g. 'callq "_setindex!"')
  and hide the first line number if it is zero

* print inlining info during jl_gdblookup

also fix llvm 3.3 build

fix JuliaLang#17317
  • Loading branch information
vtjnash authored and mfasi committed Sep 5, 2016
1 parent 032ebab commit d384434
Show file tree
Hide file tree
Showing 7 changed files with 149 additions and 113 deletions.
7 changes: 5 additions & 2 deletions base/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2910,8 +2910,11 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atypes::Vector{Any}, sv::Inference
stmts)
empty!(stmts)
else
isa(stmts[1], LineNumberNode) && shift!(stmts)
unshift!(stmts, Expr(:meta, :push_loc, linfo.def.file, linfo.def.name, linfo.def.line))
local line::Int = linfo.def.line
if isa(stmts[1], LineNumberNode)
line = shift!(stmts).line
end
unshift!(stmts, Expr(:meta, :push_loc, linfo.def.file, linfo.def.name, line))
isa(stmts[end], LineNumberNode) && pop!(stmts)
push!(stmts, Expr(:meta, :pop_loc))
end
Expand Down
18 changes: 11 additions & 7 deletions src/ccall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ static DenseMap<AttributeSet,
std::map<std::tuple<GlobalVariable*,FunctionType*,
CallingConv::ID>,GlobalVariable*>> allPltMap;

#ifdef LLVM37 // needed for musttail
// Emit a "PLT" entry that will be lazily initialized
// when being called the first time.
static Value *emit_plt(FunctionType *functype, const AttributeSet &attrs,
Expand Down Expand Up @@ -246,8 +247,8 @@ static Value *emit_plt(FunctionType *functype, const AttributeSet &attrs,
llvmgv, runtime_lib);
builder.CreateStore(builder.CreateBitCast(ptr, T_pvoidfunc), got);
SmallVector<Value*, 16> args;
for (auto &arg: plt->args())
args.push_back(&arg);
for (Function::arg_iterator arg = plt->arg_begin(), arg_e = plt->arg_end(); arg != arg_e; ++arg)
args.push_back(&*arg);
CallInst *ret = builder.CreateCall(ptr, ArrayRef<Value*>(args));
ret->setAttributes(attrs);
if (cc != CallingConv::C)
Expand Down Expand Up @@ -286,6 +287,7 @@ static Value *emit_plt(FunctionType *functype, const AttributeSet &attrs,
}
return builder.CreateBitCast(builder.CreateLoad(got), funcptype);
}
#endif

// --- ABI Implementations ---
// Partially based on the LDC ABI implementations licensed under the BSD 3-clause license
Expand Down Expand Up @@ -1694,14 +1696,16 @@ static jl_cgval_t emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx)

PointerType *funcptype = PointerType::get(functype,0);
if (imaging_mode) {
#if defined(_CPU_ARM_) || defined(_CPU_PPC_) || defined(_CPU_PPC64_)
// ARM, PPC, PPC64 (as of LLVM 3.9) doesn't support `musttail`
// for vararg functions.
if (functype)
#ifdef LLVM37
// ARM, PPC, PPC64 (as of LLVM 3.9) doesn't support `musttail` for vararg functions.
// And musttail can't proceed unreachable, but is required for vararg (https://llvm.org/bugs/show_bug.cgi?id=23766)
if (functype->isVarArg())
llvmf = runtime_sym_lookup(funcptype, f_lib, f_name, ctx->f);
else
#endif
llvmf = emit_plt(functype, attrs, cc, f_lib, f_name);
#else
llvmf = runtime_sym_lookup(funcptype, f_lib, f_name, ctx->f);
#endif
}
else {
void *symaddr = jl_dlsym_e(jl_get_library(f_lib), f_name);
Expand Down
68 changes: 41 additions & 27 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4248,14 +4248,13 @@ static std::unique_ptr<Module> emit_function(jl_lambda_info_t *lam, jl_llvm_func
(jl_options.malloc_log == JL_LOG_USER && in_user_code);
StringRef filename = "<missing>";
StringRef dbgFuncName = ctx.name;
int lno = -1;
int toplineno = -1;
if (lam->def) {
lno = lam->def->line;
toplineno = lam->def->line;
if (lam->def->file != empty_sym)
filename = jl_symbol_name(lam->def->file);
}
ctx.file = filename;
int toplineno = lno;

DIBuilder dbuilder(*M);
ctx.dbuilder = &dbuilder;
Expand All @@ -4267,15 +4266,17 @@ static std::unique_ptr<Module> emit_function(jl_lambda_info_t *lam, jl_llvm_func
#else
DIFile topfile;
DISubprogram SP;
std::vector<DebugLoc> DI_loc_stack;
std::vector<DISubprogram> DI_sp_stack;
#endif

BasicBlock *b0 = BasicBlock::Create(jl_LLVMContext, "top", f);
builder.SetInsertPoint(b0);

// jl_printf(JL_STDERR, "\n*** compiling %s at %s:%d\n\n",
// jl_symbol_name(lam->name), filename.c_str(), lno);
// jl_symbol_name(lam->name), filename.c_str(), toplineno);

DebugLoc noDbg;
DebugLoc noDbg, topdebugloc;
ctx.debug_enabled = true;
if (dbgFuncName.empty()) {
// special value: if function name is empty, disable debug info
Expand Down Expand Up @@ -4348,18 +4349,15 @@ static std::unique_ptr<Module> emit_function(jl_lambda_info_t *lam, jl_llvm_func
#else
f); // Function
#endif
// set initial line number
builder.SetCurrentDebugLocation(DebugLoc::get(lno, 0, (MDNode*)SP, NULL));
topdebugloc = DebugLoc::get(toplineno, 0, SP, NULL);
#ifdef LLVM38
f->setSubprogram(SP);
#endif
#ifndef LLVM37
assert(SP.Verify() && SP.describes(f) && SP.getFunction() == f);
#endif
}
else {
builder.SetCurrentDebugLocation(noDbg);
}
builder.SetCurrentDebugLocation(noDbg);

if (ctx.debug_enabled) {
const bool AlwaysPreserve = true;
Expand Down Expand Up @@ -4519,7 +4517,7 @@ static std::unique_ptr<Module> emit_function(jl_lambda_info_t *lam, jl_llvm_func
assert((Metadata*)varinfo.dinfo->getType() != jl_pvalue_dillvmt);
ctx.dbuilder->insertDeclare(lv, varinfo.dinfo, ctx.dbuilder->createExpression(),
#ifdef LLVM37
builder.getCurrentDebugLocation(),
topdebugloc,
#endif
builder.GetInsertBlock());
}
Expand Down Expand Up @@ -4547,7 +4545,7 @@ static std::unique_ptr<Module> emit_function(jl_lambda_info_t *lam, jl_llvm_func
}
ctx.dbuilder->insertDeclare(av, varinfo.dinfo, expr,
#ifdef LLVM37
builder.getCurrentDebugLocation(),
topdebugloc,
#endif
builder.GetInsertBlock());
}
Expand Down Expand Up @@ -4606,7 +4604,7 @@ static std::unique_ptr<Module> emit_function(jl_lambda_info_t *lam, jl_llvm_func
addr.push_back(llvm::dwarf::DW_OP_deref);
ctx.dbuilder->insertDeclare(pargArray, vi.dinfo, ctx.dbuilder->createExpression(addr),
#ifdef LLVM37
builder.getCurrentDebugLocation(),
topdebugloc,
#endif
builder.GetInsertBlock());
}
Expand Down Expand Up @@ -4638,7 +4636,7 @@ static std::unique_ptr<Module> emit_function(jl_lambda_info_t *lam, jl_llvm_func
}
ctx.dbuilder->insertDeclare(parg, vi.dinfo, ctx.dbuilder->createExpression(addr),
#ifdef LLVM37
builder.getCurrentDebugLocation(),
topdebugloc,
#endif
builder.GetInsertBlock());
}
Expand Down Expand Up @@ -4718,11 +4716,14 @@ static std::unique_ptr<Module> emit_function(jl_lambda_info_t *lam, jl_llvm_func
}

// step 13. compile body statements
if (ctx.debug_enabled)
// set initial line number
builder.SetCurrentDebugLocation(topdebugloc);
bool prevlabel = false;
lno = -1;
int lno = -1;
int prevlno = -1;
for(i=0; i < stmtslen; i++) {
jl_value_t *stmt = jl_array_ptr_ref(stmts,i);
for (i = 0; i < stmtslen; i++) {
jl_value_t *stmt = jl_array_ptr_ref(stmts, i);
if (jl_is_linenode(stmt) ||
(jl_is_expr(stmt) && ((jl_expr_t*)stmt)->head == line_sym)) {

Expand All @@ -4733,23 +4734,30 @@ static std::unique_ptr<Module> emit_function(jl_lambda_info_t *lam, jl_llvm_func
lno = jl_unbox_long(jl_exprarg(stmt,0));
}
MDNode *inlinedAt = NULL;
#ifdef LLVM37
if (DI_loc_stack.size() > 0) {
#ifdef LLVM37
inlinedAt = DI_loc_stack.back();
}
#else
inlinedAt = DI_loc_stack.back().getAsMDNode(jl_LLVMContext);
#endif
if (ctx.debug_enabled) builder.SetCurrentDebugLocation(DebugLoc::get(lno, 0, (MDNode*)SP, inlinedAt));
}
if (ctx.debug_enabled)
builder.SetCurrentDebugLocation(DebugLoc::get(lno, 0, SP, inlinedAt));
}
else if (ctx.debug_enabled && jl_is_expr(stmt) && ((jl_expr_t*)stmt)->head == meta_sym && jl_array_len(((jl_expr_t*)stmt)->args) >= 1) {
#ifdef LLVM37
jl_expr_t *stmt_e = (jl_expr_t*)stmt;
jl_value_t *meta_arg = jl_exprarg(stmt_e, 0);
if (meta_arg == (jl_value_t*)jl_symbol("push_loc")) {
std::string new_filename = "<missing>";
assert(jl_array_len(stmt_e->args) > 1);
jl_sym_t *filesym = (jl_sym_t*)jl_exprarg(stmt_e, 1);
new_filename = jl_symbol_name(filesym);
if (filesym != empty_sym)
new_filename = jl_symbol_name(filesym);
#ifdef LLVM37
DIFile *new_file = dbuilder.createFile(new_filename, ".");
#else
DIFile new_file = dbuilder.createFile(new_filename, ".");
#endif
DI_sp_stack.push_back(SP);
DI_loc_stack.push_back(builder.getCurrentDebugLocation());
std::string inl_name;
Expand All @@ -4760,8 +4768,10 @@ static std::unique_ptr<Module> emit_function(jl_lambda_info_t *lam, jl_llvm_func
jl_value_t *arg = jl_exprarg(stmt_e, ii);
if (jl_is_symbol(arg))
inl_name = jl_symbol_name((jl_sym_t*)arg);
else if (jl_is_long(arg))
inlined_func_lineno = jl_unbox_long(arg);
else if (jl_is_int32(arg))
inlined_func_lineno = jl_unbox_int32(arg);
else if (jl_is_int64(arg))
inlined_func_lineno = jl_unbox_int64(arg);
}
}
else {
Expand All @@ -4779,18 +4789,22 @@ static std::unique_ptr<Module> emit_function(jl_lambda_info_t *lam, jl_llvm_func
0,
true,
nullptr);
builder.SetCurrentDebugLocation(DebugLoc::get(inlined_func_lineno, 0, (MDNode*)SP, builder.getCurrentDebugLocation()));
MDNode *inlinedAt = NULL;
#ifdef LLVM37
inlinedAt = builder.getCurrentDebugLocation();
#else
inlinedAt = builder.getCurrentDebugLocation().getAsMDNode(jl_LLVMContext);
#endif
builder.SetCurrentDebugLocation(DebugLoc::get(inlined_func_lineno, 0, SP, inlinedAt));
}
else if (meta_arg == (jl_value_t*)jl_symbol("pop_loc")) {
SP = DI_sp_stack.back();
DI_sp_stack.pop_back(); // because why not make pop a void function
builder.SetCurrentDebugLocation(DI_loc_stack.back());
DI_loc_stack.pop_back();
}
#endif
}

DebugLoc loc;
if (do_coverage)
coverageVisitLine(filename, lno);
if (jl_is_labelnode(stmt)) {
Expand Down
81 changes: 46 additions & 35 deletions src/debuginfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -662,7 +662,7 @@ JITEventListener *CreateJuliaJITEventListener()
static int lookup_pointer(DIContext *context, jl_frame_t **frames,
size_t pointer, int demangle, int noInline)
{
// This function is not allowed to reference any TLS variables if noInline
// This function is not allowed to reference any TLS variables
// since it can be called from an unmanaged thread on OSX.
if (!context) {
if (demangle && (*frames)[0].func_name != NULL) {
Expand All @@ -689,7 +689,7 @@ static int lookup_pointer(DIContext *context, jl_frame_t **frames,
n_frames = 1;
if (n_frames > 1) {
jl_frame_t *new_frames = (jl_frame_t*)calloc(sizeof(jl_frame_t), n_frames);
memcpy(&new_frames[n_frames-1], *frames, sizeof(jl_frame_t));
memcpy(&new_frames[n_frames - 1], *frames, sizeof(jl_frame_t));
free(*frames);
*frames = new_frames;
}
Expand Down Expand Up @@ -1277,50 +1277,61 @@ int jl_getFunctionInfo(jl_frame_t **frames_out, size_t pointer, int skipC, int n
std::vector<JITEvent_EmittedFunctionDetails::LineStart>::iterator vit =
(*it).second.lines.begin();
JITEvent_EmittedFunctionDetails::LineStart prev = *vit;

if ((*it).second.func) {
DISubprogram debugscope =
DISubprogram(prev.Loc.getScope((*it).second.func->getContext()));
jl_copy_str(&frames[0].file_name, debugscope.getFilename().str().c_str());
// the DISubprogram has the un-mangled name, so use that if
// available. However, if the scope need not be the current
// subprogram.
if (debugscope.getName().data() != NULL) {
jl_copy_str(&frames[0].func_name, debugscope.getName().str().c_str());
}
else {
char *oldname = frames[0].func_name;
frames[0].func_name = jl_demangle(frames[0].func_name);
free(oldname);
}
LLVMContext &Ctx = (*it).second.func->getContext();

DISubprogram debugscope(prev.Loc.getScope(Ctx));
jl_copy_str(&frames[0].file_name, debugscope.getFilename().str().c_str());
// the DISubprogram has the un-mangled name, so use that if
// available. However, if the scope need not be the current
// subprogram.
if (debugscope.getName().data() != NULL) {
jl_copy_str(&frames[0].func_name, debugscope.getName().str().c_str());
}
else {
char *oldname = frames[0].func_name;
frames[0].func_name = jl_demangle(frames[0].func_name);
free(oldname);
}

vit++;

// find nearest line info
++vit;
while (vit != (*it).second.lines.end()) {
if (pointer <= (*vit).Address) {
frames[0].line = prev.Loc.getLine();
break;
}
prev = *vit;
vit++;
}
if (frames[0].line == -1) {
frames[0].line = prev.Loc.getLine();
++vit;
}

DILexicalBlockFile locscope = DILexicalBlockFile(prev.Loc.getScope((*it).second.func->getContext()));
jl_copy_str(&frames[0].file_name, locscope.getFilename().str().c_str());
// read out inlining and line number information
int n_frames = 1;
if (!noInline) {
MDNode *inlinedAt = prev.Loc.getInlinedAt(Ctx);
while (inlinedAt != NULL) {
DebugLoc inlineloc = DebugLoc::getFromDILocation(inlinedAt);
inlinedAt = inlineloc.getInlinedAt(Ctx);
n_frames++;
}
if (n_frames > 1) {
frames = (jl_frame_t*)calloc(sizeof(jl_frame_t), n_frames);
memcpy(&frames[n_frames - 1], *frames_out, sizeof(jl_frame_t));
free(*frames_out);
*frames_out = frames;
}
}
DebugLoc inlineloc = prev.Loc;
for (int i = 0; i < n_frames; i++) {
frames[i].inlined = i != n_frames - 1;
frames[i].line = inlineloc.getLine();
DISubprogram locscope(inlineloc.getScope(Ctx));
jl_copy_str(&frames[i].file_name, locscope.getFilename().str().c_str());
jl_copy_str(&frames[i].func_name, locscope.getName().str().c_str());
MDNode *inlinedAt = inlineloc.getInlinedAt(Ctx);
inlineloc = DebugLoc::getFromDILocation(inlinedAt);
}

/*MDNode *inlinedAt = skipInline ? NULL : prev.Loc.getInlinedAt((*it).second.func->getContext());
if ((!skipInline) && (inlinedAt != NULL)) {
DebugLoc inlineloc = DebugLoc::getFromDILocation(inlinedAt);
DILexicalBlockFile inlinescope = DILexicalBlockFile(inlineloc.getScope((*it).second.func->getContext()));
jl_copy_str(&frames, inlinescope.getFilename().str().c_str());
*inlinedat_line = inlineloc.getLine();
}*/
uv_rwlock_rdunlock(&threadsafe);
return 1;
return n_frames;
}
uv_rwlock_rdunlock(&threadsafe);
#endif // USE_MCJIT
Expand Down
Loading

0 comments on commit d384434

Please sign in to comment.