hacks to make thedebugger work again.

This commit is contained in:
Jeff Hutchinson 2021-08-14 01:37:01 -04:00
parent 717c7acca9
commit a449fadde2
8 changed files with 123 additions and 9 deletions

View file

@ -62,6 +62,7 @@ class FuncVars
{
S32 reg;
TypeReq currentType;
StringTableEntry name;
bool isConstant;
};
@ -76,7 +77,9 @@ public:
}
S32 id = counter++;
vars[var] = { id, currentType, isConstant };
vars[var] = { id, currentType, var, isConstant };
variableNameMap[id] = var;
return id;
}
@ -97,6 +100,8 @@ public:
inline S32 count() { return counter; }
std::unordered_map<S32, StringTableEntry> variableNameMap;
private:
std::unordered_map<StringTableEntry, Var> vars;
S32 counter = 0;
@ -1604,6 +1609,14 @@ U32 FunctionDeclStmtNode::compileStmt(CodeStream& codeStream, U32 ip)
setCurrentStringTable(&getGlobalStringTable());
setCurrentFloatTable(&getGlobalFloatTable());
// map local variables to registers for this function.
CompilerLocalVariableToRegisterMappingTable* tbl = &getFunctionVariableMappingTable();
for (const auto& pair : gFuncVars->variableNameMap)
{
tbl->add(fnName, pair.second, pair.first);
}
gFuncVars = NULL;
return ip;

View file

@ -640,6 +640,8 @@ ConsoleValue CodeBlock::compileExec(StringTableEntry fileName, const char *inStr
globalFloats = getGlobalFloatTable().build();
functionFloats = getFunctionFloatTable().build();
variableRegisterTable = getFunctionVariableMappingTable().copy();
codeStream.emit(OP_RETURN_VOID);
codeStream.emitCodeStream(&codeSize, &code, &lineBreakPairs);

View file

@ -23,6 +23,24 @@
#ifndef _CODEBLOCK_H_
#define _CODEBLOCK_H_
#include <unordered_map>
struct CompilerLocalVariableToRegisterMappingTable
{
// First key: function name
struct RemappingTable
{
std::unordered_map<StringTableEntry, S32> table;
};
std::unordered_map<StringTableEntry, RemappingTable> localVarToRegister;
void add(StringTableEntry functionName, StringTableEntry varName, S32 reg);
S32 lookup(StringTableEntry functionName, StringTableEntry varName);
CompilerLocalVariableToRegisterMappingTable copy();
void reset();
};
#include "console/compiler.h"
#include "console/consoleParser.h"
@ -34,7 +52,6 @@ class ConsoleValue;
/// This class represents a block of code, usually mapped directly to a file.
class CodeBlock
{
friend class CodeInterpreter;
private:
static CodeBlock* smCodeBlockList;
static CodeBlock* smCurrentCodeBlock;
@ -77,6 +94,8 @@ public:
U32 codeSize;
U32 *code;
CompilerLocalVariableToRegisterMappingTable variableRegisterTable;
U32 refCount;
U32 lineBreakPairCount;
U32 *lineBreakPairs;

View file

@ -1773,8 +1773,8 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
//if this is called from inside a function, append the ip and codeptr
if (!gEvalState.stack.empty())
{
gEvalState.stack.last()->code = this;
gEvalState.stack.last()->ip = ip - 1;
gEvalState.getCurrentFrame().code = this;
gEvalState.getCurrentFrame().ip = ip - 1;
}
ip += 5;
@ -2070,8 +2070,8 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
{
//append the ip and codeptr before managing the breakpoint!
AssertFatal(!gEvalState.stack.empty(), "Empty eval stack on break!");
gEvalState.stack.last()->code = this;
gEvalState.stack.last()->ip = ip - 1;
gEvalState.getCurrentFrame().code = this;
gEvalState.getCurrentFrame().ip = ip - 1;
U32 breakLine;
findBreakLine(ip - 1, breakLine, instruction);

View file

@ -60,6 +60,7 @@ namespace Compiler
CompilerFloatTable *gCurrentFloatTable, gGlobalFloatTable, gFunctionFloatTable;
DataChunker gConsoleAllocator;
CompilerIdentTable gIdentTable;
CompilerLocalVariableToRegisterMappingTable gFunctionVariableMappingTable;
//------------------------------------------------------------
@ -92,6 +93,8 @@ namespace Compiler
CompilerStringTable &getGlobalStringTable() { return gGlobalStringTable; }
CompilerStringTable &getFunctionStringTable() { return gFunctionStringTable; }
CompilerLocalVariableToRegisterMappingTable& getFunctionVariableMappingTable() { return gFunctionVariableMappingTable; }
void setCurrentStringTable(CompilerStringTable* cst) { gCurrentStringTable = cst; }
CompilerFloatTable *getCurrentFloatTable() { return gCurrentFloatTable; }
@ -117,6 +120,7 @@ namespace Compiler
getFunctionFloatTable().reset();
getFunctionStringTable().reset();
getIdentTable().reset();
getFunctionVariableMappingTable().reset();
}
void *consoleAlloc(U32 size) { return gConsoleAllocator.alloc(size); }
@ -208,6 +212,43 @@ void CompilerStringTable::write(Stream &st)
//------------------------------------------------------------
void CompilerLocalVariableToRegisterMappingTable::add(StringTableEntry functionName, StringTableEntry varName, S32 reg)
{
localVarToRegister[functionName].table[varName] = reg;
}
S32 CompilerLocalVariableToRegisterMappingTable::lookup(StringTableEntry functionName, StringTableEntry varName)
{
auto functionPosition = localVarToRegister.find(functionName);
if (functionPosition != localVarToRegister.end())
{
const auto& table = localVarToRegister[functionName].table;
auto varPosition = table.find(varName);
if (varPosition != table.end())
{
return varPosition->second;
}
}
Con::errorf("Unable to find local variable %s in function name %s", varName, functionName);
return -1;
}
CompilerLocalVariableToRegisterMappingTable CompilerLocalVariableToRegisterMappingTable::copy()
{
// Trivilly copyable as its all plain old data and using STL containers... (We want a deep copy though!)
CompilerLocalVariableToRegisterMappingTable table;
table.localVarToRegister = localVarToRegister;
return std::move(table);
}
void CompilerLocalVariableToRegisterMappingTable::reset()
{
localVarToRegister.clear();
}
//------------------------------------------------------------
U32 CompilerFloatTable::add(F64 value)
{
Entry **walk;

View file

@ -44,6 +44,8 @@ class DataChunker;
#include "core/util/tVector.h"
#endif
//------------------------------------------------------------
namespace Compiler
{
/// The opcodes for the TorqueScript VM.
@ -252,6 +254,7 @@ namespace Compiler
CompilerStringTable *getCurrentStringTable();
CompilerStringTable &getGlobalStringTable();
CompilerStringTable &getFunctionStringTable();
CompilerLocalVariableToRegisterMappingTable& getFunctionVariableMappingTable();
void setCurrentStringTable(CompilerStringTable* cst);

View file

@ -644,6 +644,11 @@ public:
return *(stack[mStackDepth - 1]);
}
Dictionary& getFrameAt(S32 depth)
{
return *(stack[depth]);
}
/// @}
/// Run integrity checks for debugging.

View file

@ -864,6 +864,37 @@ void TelnetDebugger::evaluateExpression(const char *tag, S32 frame, const char *
if ( frame < 0 )
frame = 0;
// Local variables use their own memory management and can't be queried by just executing
// TorqueScript, we have to go digging into the interpreter.
S32 evalBufferLen = dStrlen(evalBuffer);
bool isEvaluatingLocalVariable = evalBufferLen > 0 && evalBuffer[0] == '%';
if (isEvaluatingLocalVariable)
{
const char* format = "EVALOUT %s %s\r\n";
Dictionary &stackFrame = gEvalState.getFrameAt(frame);
StringTableEntry functionName = stackFrame.scopeName;
S32 registerId = stackFrame.code->variableRegisterTable.lookup(functionName, StringTable->insert(evalBuffer));
if (registerId == -1)
{
// ERROR, can't read the variable!
send("EVALOUT \"\" \"\"");
return;
}
const char* varResult = gEvalState.getLocalStringVariable(registerId);
S32 len = dStrlen(format) + dStrlen(tag) + dStrlen(varResult);
char* buffer = new char[len];
dSprintf(buffer, len, format, tag, varResult[0] ? varResult : "\"\"");
send(buffer);
delete[] buffer;
return;
}
// Build a buffer just big enough for this eval.
const char* format = "return %s;";
dsize_t len = dStrlen( format ) + dStrlen( evalBuffer );
@ -872,14 +903,14 @@ void TelnetDebugger::evaluateExpression(const char *tag, S32 frame, const char *
// Execute the eval.
CodeBlock *newCodeBlock = new CodeBlock();
const char* result = newCodeBlock->compileExec( NULL, buffer, false, frame );
ConsoleValue result = newCodeBlock->compileExec( NULL, buffer, false, frame );
delete [] buffer;
// Create a new buffer that fits the result.
format = "EVALOUT %s %s\r\n";
len = dStrlen( format ) + dStrlen( tag ) + dStrlen( result );
len = dStrlen( format ) + dStrlen( tag ) + dStrlen( result.getString() );
buffer = new char[ len ];
dSprintf( buffer, len, format, tag, result[0] ? result : "\"\"" );
dSprintf( buffer, len, format, tag, result.getString()[0] ? result.getString() : "\"\"" );
send( buffer );
delete [] buffer;