diff --git a/src/dsql/BlrDebugWriter.cpp b/src/dsql/BlrDebugWriter.cpp index 5f7868575e..864264b066 100644 --- a/src/dsql/BlrDebugWriter.cpp +++ b/src/dsql/BlrDebugWriter.cpp @@ -103,7 +103,7 @@ void BlrDebugWriter::putDebugArgument(UCHAR type, USHORT number, const TEXT* nam debugData.add(reinterpret_cast(name), len); } -void BlrDebugWriter::putDebugCursor(USHORT number, const MetaName& name) +void BlrDebugWriter::putDebugDeclaredCursor(USHORT number, const MetaName& name) { if (debugData.isEmpty()) return; @@ -119,6 +119,21 @@ void BlrDebugWriter::putDebugCursor(USHORT number, const MetaName& name) debugData.add(reinterpret_cast(name.c_str()), len); } +void BlrDebugWriter::putDebugForCursor(const MetaName& name) +{ + if (debugData.isEmpty()) + return; + + debugData.add(fb_dbg_map_for_curname); + + putBlrOffset(); + + USHORT len = MIN(name.length(), MAX_UCHAR); + debugData.add(len); + + debugData.add(reinterpret_cast(name.c_str()), len); +} + void BlrDebugWriter::putDebugSubFunction(DeclareSubFuncNode* subFuncNode) { if (debugData.isEmpty()) diff --git a/src/dsql/BlrDebugWriter.h b/src/dsql/BlrDebugWriter.h index 7e37df4bf0..6569a65b92 100644 --- a/src/dsql/BlrDebugWriter.h +++ b/src/dsql/BlrDebugWriter.h @@ -47,7 +47,8 @@ public: void putDebugSrcInfo(ULONG, ULONG); void putDebugVariable(USHORT, const MetaName&); void putDebugArgument(UCHAR, USHORT, const TEXT*); - void putDebugCursor(USHORT, const MetaName&); + void putDebugDeclaredCursor(USHORT, const MetaName&); + void putDebugForCursor(const MetaName&); void putDebugSubFunction(DeclareSubFuncNode* subFuncNode); void putDebugSubProcedure(DeclareSubProcNode* subProcNode); diff --git a/src/dsql/StmtNodes.cpp b/src/dsql/StmtNodes.cpp index 251fdfe196..42a7ad46ab 100644 --- a/src/dsql/StmtNodes.cpp +++ b/src/dsql/StmtNodes.cpp @@ -1244,7 +1244,7 @@ DeclareCursorNode* DeclareCursorNode::dsqlPass(DsqlCompilerScratch* dsqlScratch) cursorNumber = dsqlScratch->cursorNumber++; dsqlScratch->cursors.push(this); - dsqlScratch->putDebugCursor(cursorNumber, dsqlName); + dsqlScratch->putDebugDeclaredCursor(cursorNumber, dsqlName); ++dsqlScratch->scopeLevel; @@ -1303,7 +1303,7 @@ DeclareCursorNode* DeclareCursorNode::pass2(thread_db* tdbb, CompilerScratch* cs ExprNode::doPass2(tdbb, csb, refs.getAddress()); MetaName cursorName; - csb->csb_dbg_info->curIndexToName.get(cursorNumber, cursorName); + csb->csb_dbg_info->declaredCursorIndexToName.get(cursorNumber, cursorName); // Finish up processing of record selection expressions. @@ -4881,6 +4881,9 @@ DmlNode* ForNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, { ForNode* node = FB_NEW_POOL(pool) ForNode(pool); + if (auto cursorName = csb->csb_dbg_info->forCursorOffsetToName.get(csb->csb_blr_reader.getOffset() - 1)) + csb->csb_forCursorNames.put(node, *cursorName); + if (csb->csb_blr_reader.peekByte() == blr_marks) node->marks |= PAR_marks(csb); @@ -4929,9 +4932,6 @@ ForNode* ForNode::dsqlPass(DsqlCompilerScratch* dsqlScratch) dsqlCursor->rse = node->rse; dsqlCursor->cursorNumber = dsqlScratch->cursorNumber++; dsqlScratch->cursors.push(dsqlCursor); - - // ASF: We cannot write this cursor name in debug info, as dsqlScratch->cursorNumber is - // decremented below. But for now we don't need it. } else node->rse = dsqlSelect->dsqlPass(dsqlScratch)->dsqlRse; @@ -5001,6 +5001,9 @@ void ForNode::genBlr(DsqlCompilerScratch* dsqlScratch) // Generate FOR loop + if (dsqlCursor) + dsqlScratch->putDebugForCursor(dsqlCursor->dsqlName); + dsqlScratch->appendUChar(blr_for); if (marks) @@ -5069,11 +5072,11 @@ StmtNode* ForNode::pass2(thread_db* tdbb, CompilerScratch* csb) RecordSource* const rsb = CMP_post_rse(tdbb, csb, rse.getObject()); + MetaName cursorName; + csb->csb_forCursorNames.get(this, cursorName); + cursor = FB_NEW_POOL(*tdbb->getDefaultPool()) - Cursor(csb, rsb, rse, !(marks & MARK_AVOID_COUNTERS), line, column); - // ASF: We cannot define the name of the cursor here, but this is not a problem, - // as implicit cursors are always positioned in a valid record, and the name is - // only used to raise isc_cursor_not_positioned. + Cursor(csb, rsb, rse, !(marks & MARK_AVOID_COUNTERS), line, column, cursorName); csb->csb_fors.add(cursor); diff --git a/src/include/firebird/impl/consts_pub.h b/src/include/firebird/impl/consts_pub.h index 688d952de5..d7f7004962 100644 --- a/src/include/firebird/impl/consts_pub.h +++ b/src/include/firebird/impl/consts_pub.h @@ -780,7 +780,8 @@ #define fb_dbg_map_argument 4 #define fb_dbg_subproc 5 #define fb_dbg_subfunc 6 -#define fb_dbg_map_curname 7 +#define fb_dbg_map_curname 7 /* declared cursor */ +#define fb_dbg_map_for_curname 8 /* FOR cursor */ //// TODO: LocalTable name. // sub code for fb_dbg_map_argument diff --git a/src/include/gen/Firebird.pas b/src/include/gen/Firebird.pas index f65483acaa..6e3911c7ed 100644 --- a/src/include/gen/Firebird.pas +++ b/src/include/gen/Firebird.pas @@ -4327,6 +4327,7 @@ const fb_dbg_subproc = byte(5); fb_dbg_subfunc = byte(6); fb_dbg_map_curname = byte(7); + fb_dbg_map_for_curname = byte(8); fb_dbg_arg_input = byte(0); fb_dbg_arg_output = byte(1); isc_facility = 20; diff --git a/src/jrd/DebugInterface.cpp b/src/jrd/DebugInterface.cpp index 79de9e8147..0f76ff2b7b 100644 --- a/src/jrd/DebugInterface.cpp +++ b/src/jrd/DebugInterface.cpp @@ -135,13 +135,44 @@ void DBG_parse_debug_info(ULONG length, const UCHAR* data, DbgInfo& dbgInfo) if (code == fb_dbg_map_varname) dbgInfo.varIndexToName.put(index, MetaName((const TEXT*) data, length)); else - dbgInfo.curIndexToName.put(index, MetaName((const TEXT*) data, length)); + dbgInfo.declaredCursorIndexToName.put(index, MetaName((const TEXT*) data, length)); // variable/cursor name string data += length; } break; + case fb_dbg_map_for_curname: + { + if (data + 5 > end) + { + bad_format = true; + break; + } + + // fb_dbg_map_for_curname do not exist in DBG_INFO_VERSION_1, + // so always use DBG_INFO_VERSION_2 format. + ULONG offset = *data++; + offset |= *data++ << 8; + offset |= *data++ << 16; + offset |= *data++ << 24; + + // variable/cursor name string length + USHORT length = *data++; + + if (data + length > end) + { + bad_format = true; + break; + } + + dbgInfo.forCursorOffsetToName.put(offset, MetaName((const TEXT*) data, length)); + + // cursor name string + data += length; + } + break; + case fb_dbg_map_argument: { if (data + 4 > end) diff --git a/src/jrd/DebugInterface.h b/src/jrd/DebugInterface.h index d516e6240a..fa9ee2d234 100644 --- a/src/jrd/DebugInterface.h +++ b/src/jrd/DebugInterface.h @@ -58,8 +58,6 @@ typedef Firebird::SortedArray< ULONG, MapBlrToSrcItem> MapBlrToSrc; -typedef GenericMap > > MapVarIndexToName; - struct ArgumentInfo { ArgumentInfo(UCHAR aType, USHORT aIndex) @@ -86,8 +84,6 @@ struct ArgumentInfo } }; -typedef GenericMap > > MapArgumentInfoToName; - struct DbgInfo : public PermanentStorage { explicit DbgInfo(MemoryPool& p) @@ -95,7 +91,8 @@ struct DbgInfo : public PermanentStorage blrToSrc(p), varIndexToName(p), argInfoToName(p), - curIndexToName(p), + declaredCursorIndexToName(p), + forCursorOffsetToName(p), subFuncs(p), subProcs(p) { @@ -111,10 +108,11 @@ struct DbgInfo : public PermanentStorage blrToSrc.clear(); varIndexToName.clear(); argInfoToName.clear(); - curIndexToName.clear(); + declaredCursorIndexToName.clear(); + forCursorOffsetToName.clear(); { // scope - GenericMap > >::Accessor accessor(&subFuncs); + LeftPooledMap::Accessor accessor(&subFuncs); for (bool found = accessor.getFirst(); found; found = accessor.getNext()) delete accessor.current()->second; @@ -123,7 +121,7 @@ struct DbgInfo : public PermanentStorage } { // scope - GenericMap > >::Accessor accessor(&subProcs); + LeftPooledMap::Accessor accessor(&subProcs); for (bool found = accessor.getFirst(); found; found = accessor.getNext()) delete accessor.current()->second; @@ -133,11 +131,12 @@ struct DbgInfo : public PermanentStorage } MapBlrToSrc blrToSrc; // mapping between blr offsets and source text position - MapVarIndexToName varIndexToName; // mapping between variable index and name - MapArgumentInfoToName argInfoToName; // mapping between argument info (type, index) and name - MapVarIndexToName curIndexToName; // mapping between cursor index and name - GenericMap > > subFuncs; // sub functions - GenericMap > > subProcs; // sub procedures + RightPooledMap varIndexToName; // mapping between variable index and name + RightPooledMap argInfoToName; // mapping between argument info (type, index) and name + RightPooledMap declaredCursorIndexToName; // mapping between declared cursor index and name + RightPooledMap forCursorOffsetToName; // mapping between for-cursor offset and name + LeftPooledMap subFuncs; // sub functions + LeftPooledMap subProcs; // sub procedures }; } // namespace Firebird diff --git a/src/jrd/exe.h b/src/jrd/exe.h index 5bd3114b6d..570c8c72d7 100644 --- a/src/jrd/exe.h +++ b/src/jrd/exe.h @@ -479,6 +479,7 @@ public: csb_invariants(p), csb_current_nodes(p), csb_current_for_nodes(p), + csb_forCursorNames(p), csb_computing_fields(p), csb_inner_booleans(p), csb_variables_used_in_subroutines(p), @@ -558,6 +559,7 @@ public: Firebird::Array csb_current_nodes; // RseNode's and other invariant // candidates within whose scope we are Firebird::Array csb_current_for_nodes; + Firebird::RightPooledMap csb_forCursorNames; Firebird::SortedArray csb_computing_fields; // Computed fields being compiled Firebird::Array csb_inner_booleans; // Inner booleans at the current scope Firebird::SortedArray csb_variables_used_in_subroutines; diff --git a/src/jrd/filters.cpp b/src/jrd/filters.cpp index ba1a1343ac..c8fec42111 100644 --- a/src/jrd/filters.cpp +++ b/src/jrd/filters.cpp @@ -1432,8 +1432,8 @@ ISC_STATUS filter_debug_info(USHORT action, BlobControl* control) string str; - MapArgumentInfoToName::ConstAccessor args(&dbgInfo.argInfoToName); - if (args.getFirst()) + if (auto args = dbgInfo.argInfoToName.constAccessor(); + args.getFirst()) { string_put(control, "Parameters:"); str.printf("%10s %-32s %-6s", "Number", "Name", "Type"); @@ -1453,8 +1453,8 @@ ISC_STATUS filter_debug_info(USHORT action, BlobControl* control) string_put(control, ""); } - MapVarIndexToName::ConstAccessor vars(&dbgInfo.varIndexToName); - if (vars.getFirst()) + if (auto vars = dbgInfo.varIndexToName.constAccessor(); + vars.getFirst()) { string_put(control, "Variables:"); str.printf("%10s %-32s", "Number", "Name"); @@ -1471,8 +1471,8 @@ ISC_STATUS filter_debug_info(USHORT action, BlobControl* control) string_put(control, ""); } - MapVarIndexToName::ConstAccessor cursors(&dbgInfo.curIndexToName); - if (cursors.getFirst()) + if (auto cursors = dbgInfo.declaredCursorIndexToName.constAccessor(); + cursors.getFirst()) { string_put(control, "Cursors:"); str.printf("%10s %-32s", "Number", "Name"); @@ -1489,6 +1489,24 @@ ISC_STATUS filter_debug_info(USHORT action, BlobControl* control) string_put(control, ""); } + if (auto cursors = dbgInfo.forCursorOffsetToName.constAccessor(); + cursors.getFirst()) + { + string_put(control, "FOR Cursors:"); + str.printf("%10s %-32s", "Offset", "Name"); + string_put(control, str.c_str()); + str.replace(str.begin(), str.end(), str.length(), '-'); + string_put(control, str.c_str()); + + do + { + str.printf("%10d %-32s", cursors.current()->first, cursors.current()->second.c_str()); + string_put(control, str.c_str()); + } while (cursors.getNext()); + + string_put(control, ""); + } + string_put(control, "BLR to Source mapping:"); str.printf("%10s %10s %10s", "BLR offset", "Line", "Column"); string_put(control, str.c_str()); diff --git a/src/jrd/recsrc/Cursor.h b/src/jrd/recsrc/Cursor.h index 8145e479c1..f0b6fb59e6 100644 --- a/src/jrd/recsrc/Cursor.h +++ b/src/jrd/recsrc/Cursor.h @@ -101,7 +101,7 @@ namespace Jrd public: Cursor(CompilerScratch* csb, const RecordSource* rsb, const RseNode* rse, - bool updateCounters, ULONG line, ULONG column, const MetaName& name = ""); + bool updateCounters, ULONG line, ULONG column, const MetaName& name); void open(thread_db* tdbb) const override; void close(thread_db* tdbb) const override;