@@ -1625,13 +1625,13 @@ static void visitLine(jl_codectx_t &ctx, std::vector<logdata_block*> &vec, int l
16251625 logdata_block &data = *vec[block];
16261626 if (data[line] == 0 )
16271627 data[line] = 1 ;
1628- Value *v = ConstantExpr::getIntToPtr (
1628+ Value *pv = ConstantExpr::getIntToPtr (
16291629 ConstantInt::get (T_size, (uintptr_t )&data[line]),
16301630 T_pint64);
1631- ctx.builder .CreateStore (ctx. builder . CreateAdd (ctx. builder . CreateLoad (v , true , name),
1632- addend),
1633- v, true ); // not atomic, so this might be an underestimate,
1634- // but it's faster this way
1631+ Value *v = ctx.builder .CreateLoad (pv , true , name);
1632+ v = ctx. builder . CreateAdd (v, addend);
1633+ ctx. builder . CreateStore ( v, pv, true ); // volatile, not atomic, so this might be an underestimate,
1634+ // but it's faster this way
16351635}
16361636
16371637// Code coverage
@@ -1653,10 +1653,8 @@ static logdata_t mallocData;
16531653static void mallocVisitLine (jl_codectx_t &ctx, StringRef filename, int line)
16541654{
16551655 assert (!imaging_mode);
1656- if (filename == " " || filename == " none" || filename == " no file" || filename == " <missing>" || line < 0 ) {
1657- jl_gc_sync_total_bytes ();
1656+ if (filename == " " || filename == " none" || filename == " no file" || filename == " <missing>" || line < 0 )
16581657 return ;
1659- }
16601658 Value *addend = ctx.builder .CreateCall (prepare_call (diff_gc_total_bytes_func), {});
16611659 visitLine (ctx, mallocData[filename], line, addend, " bytecnt" );
16621660}
@@ -5288,31 +5286,30 @@ static std::unique_ptr<Module> emit_function(
52885286 // step 1b. unpack debug information
52895287 int coverage_mode = jl_options.code_coverage ;
52905288 int malloc_log_mode = jl_options.malloc_log ;
5291- StringRef filename = " <missing>" ;
5289+ if (!JL_FEAT_TEST (ctx, code_coverage))
5290+ coverage_mode = JL_LOG_NONE;
5291+ if (!JL_FEAT_TEST (ctx, track_allocations))
5292+ malloc_log_mode = JL_LOG_NONE;
5293+
5294+ ctx.file = " <missing>" ;
52925295 StringRef dbgFuncName = ctx.name ;
52935296 int toplineno = -1 ;
52945297 if (jl_is_method (lam->def .method )) {
52955298 toplineno = lam->def .method ->line ;
52965299 if (lam->def .method ->file != empty_sym)
5297- filename = jl_symbol_name (lam->def .method ->file );
5300+ ctx. file = jl_symbol_name (lam->def .method ->file );
52985301 }
52995302 else if (jl_array_len (src->linetable ) > 0 ) {
53005303 jl_value_t *locinfo = jl_array_ptr_ref (src->linetable , 0 );
5301- filename = jl_symbol_name ((jl_sym_t *)jl_fieldref_noalloc (locinfo, 2 ));
5304+ ctx. file = jl_symbol_name ((jl_sym_t *)jl_fieldref_noalloc (locinfo, 2 ));
53025305 toplineno = jl_unbox_long (jl_fieldref (locinfo, 3 ));
53035306 }
5304- ctx.file = filename;
53055307 // jl_printf(JL_STDERR, "\n*** compiling %s at %s:%d\n\n",
5306- // jl_symbol_name(ctx.name), filename .str().c_str(), toplineno);
5308+ // jl_symbol_name(ctx.name), ctx.file .str().c_str(), toplineno);
53075309
53085310 ctx.debug_enabled = true ;
5309- if (dbgFuncName.empty ()) {
5310- // special value: if function name is empty, disable debug info
5311- coverage_mode = JL_LOG_NONE;
5312- malloc_log_mode = JL_LOG_NONE;
5313- // dbgFuncName = filename; // for testing, uncomment this line
5314- ctx.debug_enabled = !dbgFuncName.empty ();
5315- }
5311+ if (dbgFuncName.empty ()) // Should never happen anymore?
5312+ ctx.debug_enabled = 0 ;
53165313 if (jl_options.debug_level == 0 )
53175314 ctx.debug_enabled = 0 ;
53185315
@@ -5481,7 +5478,7 @@ static std::unique_ptr<Module> emit_function(
54815478 DebugLoc noDbg, topdebugloc;
54825479 if (ctx.debug_enabled ) {
54835480 // TODO: Fix when moving to new LLVM version
5484- topfile = dbuilder.createFile (filename , " ." );
5481+ topfile = dbuilder.createFile (ctx. file , " ." );
54855482 DICompileUnit *CU = dbuilder.createCompileUnit (0x01 , topfile, " julia" , true , " " , 0 );
54865483 DISubroutineType *subrty;
54875484 if (jl_options.debug_level <= 1 ) {
@@ -5862,92 +5859,57 @@ static std::unique_ptr<Module> emit_function(
58625859 !jl_is_submodule (mod, jl_core_module));
58635860 };
58645861 bool mod_is_user_mod = in_user_mod (ctx.module );
5865- struct StmtProp {
5862+ struct DebugLineTable {
58665863 DebugLoc loc;
58675864 StringRef file;
58685865 ssize_t line;
5869- bool loc_changed;
5870- bool is_poploc;
5871- bool in_user_code;
5866+ bool is_user_code;
5867+ unsigned inlined_at;
58725868 };
5873- std::vector<StmtProp> stmtprops (stmtslen);
5874- { // if new style IR
5875- std::vector<DebugLoc> linetable;
5869+ std::vector<DebugLineTable> linetable;
5870+ {
58765871 size_t nlocs = jl_array_len (src->linetable );
5877- if (ctx.debug_enabled ) {
5878- std::map<std::tuple<StringRef, StringRef>, DISubprogram*> subprograms;
5879- linetable.resize (nlocs + 1 );
5880- linetable[0 ] = noDbg;
5881- for (size_t i = 0 ; i < nlocs; i++) {
5882- // LineInfoNode(mod::Module, method::Symbol, file::Symbol, line::Int, inlined_at::Int)
5883- jl_value_t *locinfo = jl_array_ptr_ref (src->linetable , i);
5884- int inlined_at, line;
5885- jl_sym_t *file;
5886- StringRef filename = ctx.file ;
5887- StringRef fname;
5888- assert (jl_typeis (locinfo, jl_lineinfonode_type));
5889- {
5890- jl_sym_t *method = (jl_sym_t *)jl_fieldref_noalloc (locinfo, 1 );
5891- file = (jl_sym_t *)jl_fieldref_noalloc (locinfo, 2 );
5892- line = jl_unbox_long (jl_fieldref (locinfo, 3 ));
5893- inlined_at = jl_unbox_long (jl_fieldref (locinfo, 4 ));
5894- assert ((size_t )inlined_at <= i);
5895- filename = jl_symbol_name (file);
5896- if (filename.empty ())
5897- filename = " <missing>" ;
5898- fname = jl_symbol_name (method);
5899- if (fname.empty ())
5900- fname = " macro expansion" ;
5901- }
5902- if (inlined_at == 0 && filename == ctx.file ) { // if everything matches, emit a toplevel line number
5903- linetable[i + 1 ] = DebugLoc::get (line, 0 , SP, NULL );
5872+ std::map<std::tuple<StringRef, StringRef>, DISubprogram*> subprograms;
5873+ linetable.resize (nlocs + 1 );
5874+ for (size_t i = 0 ; i < nlocs; i++) {
5875+ // LineInfoNode(mod::Module, method::Symbol, file::Symbol, line::Int, inlined_at::Int)
5876+ jl_value_t *locinfo = jl_array_ptr_ref (src->linetable , i);
5877+ DebugLineTable &info = linetable[i + 1 ];
5878+ assert (jl_typeis (locinfo, jl_lineinfonode_type));
5879+ jl_module_t *module = (jl_module_t *)jl_fieldref_noalloc (locinfo, 0 );
5880+ if (module == ctx.module )
5881+ info.is_user_code = mod_is_user_mod;
5882+ else
5883+ info.is_user_code = in_user_mod (module );
5884+ jl_sym_t *method = (jl_sym_t *)jl_fieldref_noalloc (locinfo, 1 );
5885+ jl_sym_t *filesym = (jl_sym_t *)jl_fieldref_noalloc (locinfo, 2 );
5886+ info.line = jl_unbox_long (jl_fieldref (locinfo, 3 ));
5887+ info.inlined_at = jl_unbox_long (jl_fieldref (locinfo, 4 ));
5888+ assert (info.inlined_at <= i);
5889+ info.file = jl_symbol_name (filesym);
5890+ if (info.file .empty ())
5891+ info.file = " <missing>" ;
5892+ if (ctx.debug_enabled ) {
5893+ StringRef fname = jl_symbol_name (method);
5894+ if (fname.empty ())
5895+ fname = " macro expansion" ;
5896+ if (info.inlined_at == 0 && info.file == ctx.file ) { // if everything matches, emit a toplevel line number
5897+ info.loc = DebugLoc::get (info.line , 0 , SP, NULL );
59045898 }
59055899 else { // otherwise, describe this as an inlining frame
5906- DISubprogram *&inl_SP = subprograms[std::make_tuple (fname, filename )];
5900+ DISubprogram *&inl_SP = subprograms[std::make_tuple (fname, info. file )];
59075901 if (inl_SP == NULL ) {
5908- DIFile *difile = dbuilder.createFile (filename , " ." );
5902+ DIFile *difile = dbuilder.createFile (info. file , " ." );
59095903 inl_SP = dbuilder.createFunction (
59105904 difile, std::string (fname) + " ;" ,
59115905 fname, difile, 0 , jl_di_func_null_sig,
59125906 false , true , 0 , DIFlagZero, true , nullptr );
59135907 }
5914- DebugLoc inl_loc = (inlined_at == 0 ) ? DebugLoc::get (0 , 0 , SP, NULL ) : linetable.at (inlined_at);
5915- linetable[i + 1 ] = DebugLoc::get (line, 0 , inl_SP, inl_loc);
5908+ DebugLoc inl_loc = (info. inlined_at == 0 ) ? DebugLoc::get (0 , 0 , SP, NULL ) : linetable.at (info. inlined_at ). loc ;
5909+ info. loc = DebugLoc::get (info. line , 0 , inl_SP, inl_loc);
59165910 }
59175911 }
59185912 }
5919- size_t prev_loc = 0 ;
5920- for (i = 0 ; i < stmtslen; i++) {
5921- size_t loc = ((int32_t *)jl_array_data (src->codelocs ))[i];
5922- StmtProp &cur_prop = stmtprops[i];
5923- cur_prop.is_poploc = false ;
5924- if (loc > 0 ) {
5925- jl_value_t *locinfo = jl_array_ptr_ref (src->linetable , loc - 1 );
5926- if (ctx.debug_enabled )
5927- cur_prop.loc = linetable.at (loc);
5928- else
5929- cur_prop.loc = noDbg;
5930- assert (jl_typeis (locinfo, jl_lineinfonode_type));
5931- {
5932- jl_module_t *module = (jl_module_t *)jl_fieldref_noalloc (locinfo, 0 );
5933- cur_prop.file = jl_symbol_name ((jl_sym_t *)jl_fieldref_noalloc (locinfo, 2 ));
5934- cur_prop.line = jl_unbox_long (jl_fieldref (locinfo, 3 ));
5935- if (module == ctx.module )
5936- cur_prop.in_user_code = mod_is_user_mod;
5937- else
5938- cur_prop.in_user_code = in_user_mod (module );
5939- }
5940- cur_prop.loc_changed = (loc != prev_loc); // for code-coverage
5941- prev_loc = loc;
5942- }
5943- else {
5944- cur_prop.loc = noDbg;
5945- cur_prop.file = " " ;
5946- cur_prop.line = -1 ;
5947- cur_prop.loc_changed = false ;
5948- cur_prop.in_user_code = false ;
5949- }
5950- }
59515913 }
59525914 Instruction &prologue_end = ctx.builder .GetInsertBlock ()->back ();
59535915
@@ -5957,9 +5919,6 @@ static std::unique_ptr<Module> emit_function(
59575919 std::map<int , BasicBlock*> BB;
59585920 std::map<size_t , BasicBlock*> come_from_bb;
59595921 int cursor = 0 ;
5960- // Whether we are doing codegen in statement order.
5961- // We need to update debug location if this is false even if
5962- // `loc_changed` is false.
59635922 auto find_next_stmt = [&] (int seq_next) {
59645923 // new style ir is always in dominance order, but frontend IR might not be
59655924 // `seq_next` is the next statement we want to emit
@@ -5995,15 +5954,40 @@ static std::unique_ptr<Module> emit_function(
59955954 };
59965955
59975956 auto do_coverage = [&] (bool in_user_code) {
5998- if (!JL_FEAT_TEST (ctx, code_coverage)) return false ;
59995957 return (coverage_mode == JL_LOG_ALL ||
60005958 (coverage_mode == JL_LOG_USER && in_user_code));
60015959 };
60025960 auto do_malloc_log = [&] (bool in_user_code) {
6003- if (!JL_FEAT_TEST (ctx, track_allocations)) return false ;
60045961 return (malloc_log_mode == JL_LOG_ALL ||
60055962 (malloc_log_mode == JL_LOG_USER && in_user_code));
60065963 };
5964+ std::vector<unsigned > current_lineinfo, new_lineinfo;
5965+ auto coverageVisitStmt = [&] (size_t dbg) {
5966+ if (dbg == 0 )
5967+ return ;
5968+ while (dbg) {
5969+ new_lineinfo.push_back (dbg);
5970+ dbg = linetable[dbg].inlined_at ;
5971+ }
5972+ current_lineinfo.resize (new_lineinfo.size (), 0 );
5973+ for (dbg = 0 ; dbg < new_lineinfo.size (); dbg++) {
5974+ unsigned newdbg = new_lineinfo[new_lineinfo.size () - dbg - 1 ];
5975+ if (newdbg != current_lineinfo[dbg]) {
5976+ current_lineinfo[dbg] = newdbg;
5977+ const auto &info = linetable[newdbg];
5978+ if (do_coverage (info.is_user_code ))
5979+ coverageVisitLine (ctx, info.file , info.line );
5980+ }
5981+ }
5982+ new_lineinfo.clear ();
5983+ };
5984+ auto mallocVisitStmt = [&] (unsigned dbg) {
5985+ if (!do_malloc_log (mod_is_user_mod) || dbg == 0 )
5986+ return ;
5987+ while (linetable[dbg].inlined_at )
5988+ dbg = linetable[dbg].inlined_at ;
5989+ mallocVisitLine (ctx, ctx.file , linetable[dbg].line );
5990+ };
60075991
60085992 come_from_bb[0 ] = ctx.builder .GetInsertBlock ();
60095993
@@ -6058,19 +6042,20 @@ static std::unique_ptr<Module> emit_function(
60586042 BB[label] = bb;
60596043 }
60606044
6061- if (coverage_mode != JL_LOG_NONE && do_coverage (in_user_mod (ctx.module )))
6062- coverageVisitLine (ctx, filename, toplineno);
6045+ if (do_coverage (mod_is_user_mod))
6046+ coverageVisitLine (ctx, ctx.file , toplineno);
6047+ if (do_malloc_log (mod_is_user_mod))
6048+ mallocVisitLine (ctx, ctx.file , toplineno);
60636049 find_next_stmt (0 );
60646050 while (cursor != -1 ) {
6065- auto &props = stmtprops[cursor];
6066- if (ctx.debug_enabled )
6067- ctx.builder .SetCurrentDebugLocation (props.loc );
6051+ int32_t debuginfoloc = ((int32_t *)jl_array_data (src->codelocs ))[cursor];
6052+ if (debuginfoloc > 0 ) {
6053+ if (ctx.debug_enabled )
6054+ ctx.builder .SetCurrentDebugLocation (linetable[debuginfoloc].loc );
6055+ coverageVisitStmt (debuginfoloc);
6056+ }
60686057 jl_value_t *stmt = jl_array_ptr_ref (stmts, cursor);
60696058 jl_expr_t *expr = jl_is_expr (stmt) ? (jl_expr_t *)stmt : nullptr ;
6070- // Legacy IR: disables coverage for pop_loc since it doesn't start a new expression
6071- if (props.loc_changed && do_coverage (props.in_user_code ) && !props.is_poploc ) {
6072- coverageVisitLine (ctx, props.file , props.line );
6073- }
60746059 if (expr && expr->head == unreachable_sym) {
60756060 ctx.builder .CreateUnreachable ();
60766061 find_next_stmt (-1 );
@@ -6162,8 +6147,7 @@ static std::unique_ptr<Module> emit_function(
61626147 }
61636148 }
61646149
6165- if (do_malloc_log (props.in_user_code ) && props.line != -1 )
6166- mallocVisitLine (ctx, props.file , props.line );
6150+ mallocVisitStmt (debuginfoloc);
61676151 if (toplevel)
61686152 ctx.builder .CreateStore (last_age, ctx.world_age_field );
61696153 assert (type_is_ghost (retty) || returninfo.cc == jl_returninfo_t ::SRet ||
@@ -6205,8 +6189,7 @@ static std::unique_ptr<Module> emit_function(
62056189 jl_value_t *cond = args[0 ];
62066190 int lname = jl_unbox_long (args[1 ]);
62076191 Value *isfalse = emit_condition (ctx, cond, " if" );
6208- if (do_malloc_log (props.in_user_code ) && props.line != -1 )
6209- mallocVisitLine (ctx, props.file , props.line );
6192+ mallocVisitStmt (debuginfoloc);
62106193 come_from_bb[cursor+1 ] = ctx.builder .GetInsertBlock ();
62116194 workstack.push_back (lname - 1 );
62126195 BasicBlock *ifnot = BB[lname];
@@ -6244,9 +6227,7 @@ static std::unique_ptr<Module> emit_function(
62446227 }
62456228 else {
62466229 emit_stmtpos (ctx, stmt, cursor);
6247- if (do_malloc_log (props.in_user_code ) && props.line != -1 ) {
6248- mallocVisitLine (ctx, props.file , props.line );
6249- }
6230+ mallocVisitStmt (debuginfoloc);
62506231 }
62516232 find_next_stmt (cursor + 1 );
62526233 }
0 commit comments