mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-07-14 16:14:38 +00:00
hacks to make thedebugger work again.
This commit is contained in:
parent
717c7acca9
commit
a449fadde2
8 changed files with 123 additions and 9 deletions
|
|
@ -62,6 +62,7 @@ class FuncVars
|
||||||
{
|
{
|
||||||
S32 reg;
|
S32 reg;
|
||||||
TypeReq currentType;
|
TypeReq currentType;
|
||||||
|
StringTableEntry name;
|
||||||
bool isConstant;
|
bool isConstant;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -76,7 +77,9 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
S32 id = counter++;
|
S32 id = counter++;
|
||||||
vars[var] = { id, currentType, isConstant };
|
vars[var] = { id, currentType, var, isConstant };
|
||||||
|
variableNameMap[id] = var;
|
||||||
|
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -97,6 +100,8 @@ public:
|
||||||
|
|
||||||
inline S32 count() { return counter; }
|
inline S32 count() { return counter; }
|
||||||
|
|
||||||
|
std::unordered_map<S32, StringTableEntry> variableNameMap;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unordered_map<StringTableEntry, Var> vars;
|
std::unordered_map<StringTableEntry, Var> vars;
|
||||||
S32 counter = 0;
|
S32 counter = 0;
|
||||||
|
|
@ -1604,6 +1609,14 @@ U32 FunctionDeclStmtNode::compileStmt(CodeStream& codeStream, U32 ip)
|
||||||
|
|
||||||
setCurrentStringTable(&getGlobalStringTable());
|
setCurrentStringTable(&getGlobalStringTable());
|
||||||
setCurrentFloatTable(&getGlobalFloatTable());
|
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;
|
gFuncVars = NULL;
|
||||||
|
|
||||||
return ip;
|
return ip;
|
||||||
|
|
|
||||||
|
|
@ -640,6 +640,8 @@ ConsoleValue CodeBlock::compileExec(StringTableEntry fileName, const char *inStr
|
||||||
globalFloats = getGlobalFloatTable().build();
|
globalFloats = getGlobalFloatTable().build();
|
||||||
functionFloats = getFunctionFloatTable().build();
|
functionFloats = getFunctionFloatTable().build();
|
||||||
|
|
||||||
|
variableRegisterTable = getFunctionVariableMappingTable().copy();
|
||||||
|
|
||||||
codeStream.emit(OP_RETURN_VOID);
|
codeStream.emit(OP_RETURN_VOID);
|
||||||
codeStream.emitCodeStream(&codeSize, &code, &lineBreakPairs);
|
codeStream.emitCodeStream(&codeSize, &code, &lineBreakPairs);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,24 @@
|
||||||
#ifndef _CODEBLOCK_H_
|
#ifndef _CODEBLOCK_H_
|
||||||
#define _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/compiler.h"
|
||||||
#include "console/consoleParser.h"
|
#include "console/consoleParser.h"
|
||||||
|
|
||||||
|
|
@ -34,7 +52,6 @@ class ConsoleValue;
|
||||||
/// This class represents a block of code, usually mapped directly to a file.
|
/// This class represents a block of code, usually mapped directly to a file.
|
||||||
class CodeBlock
|
class CodeBlock
|
||||||
{
|
{
|
||||||
friend class CodeInterpreter;
|
|
||||||
private:
|
private:
|
||||||
static CodeBlock* smCodeBlockList;
|
static CodeBlock* smCodeBlockList;
|
||||||
static CodeBlock* smCurrentCodeBlock;
|
static CodeBlock* smCurrentCodeBlock;
|
||||||
|
|
@ -77,6 +94,8 @@ public:
|
||||||
U32 codeSize;
|
U32 codeSize;
|
||||||
U32 *code;
|
U32 *code;
|
||||||
|
|
||||||
|
CompilerLocalVariableToRegisterMappingTable variableRegisterTable;
|
||||||
|
|
||||||
U32 refCount;
|
U32 refCount;
|
||||||
U32 lineBreakPairCount;
|
U32 lineBreakPairCount;
|
||||||
U32 *lineBreakPairs;
|
U32 *lineBreakPairs;
|
||||||
|
|
|
||||||
|
|
@ -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 this is called from inside a function, append the ip and codeptr
|
||||||
if (!gEvalState.stack.empty())
|
if (!gEvalState.stack.empty())
|
||||||
{
|
{
|
||||||
gEvalState.stack.last()->code = this;
|
gEvalState.getCurrentFrame().code = this;
|
||||||
gEvalState.stack.last()->ip = ip - 1;
|
gEvalState.getCurrentFrame().ip = ip - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ip += 5;
|
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!
|
//append the ip and codeptr before managing the breakpoint!
|
||||||
AssertFatal(!gEvalState.stack.empty(), "Empty eval stack on break!");
|
AssertFatal(!gEvalState.stack.empty(), "Empty eval stack on break!");
|
||||||
gEvalState.stack.last()->code = this;
|
gEvalState.getCurrentFrame().code = this;
|
||||||
gEvalState.stack.last()->ip = ip - 1;
|
gEvalState.getCurrentFrame().ip = ip - 1;
|
||||||
|
|
||||||
U32 breakLine;
|
U32 breakLine;
|
||||||
findBreakLine(ip - 1, breakLine, instruction);
|
findBreakLine(ip - 1, breakLine, instruction);
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,7 @@ namespace Compiler
|
||||||
CompilerFloatTable *gCurrentFloatTable, gGlobalFloatTable, gFunctionFloatTable;
|
CompilerFloatTable *gCurrentFloatTable, gGlobalFloatTable, gFunctionFloatTable;
|
||||||
DataChunker gConsoleAllocator;
|
DataChunker gConsoleAllocator;
|
||||||
CompilerIdentTable gIdentTable;
|
CompilerIdentTable gIdentTable;
|
||||||
|
CompilerLocalVariableToRegisterMappingTable gFunctionVariableMappingTable;
|
||||||
|
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
|
|
||||||
|
|
@ -92,6 +93,8 @@ namespace Compiler
|
||||||
CompilerStringTable &getGlobalStringTable() { return gGlobalStringTable; }
|
CompilerStringTable &getGlobalStringTable() { return gGlobalStringTable; }
|
||||||
CompilerStringTable &getFunctionStringTable() { return gFunctionStringTable; }
|
CompilerStringTable &getFunctionStringTable() { return gFunctionStringTable; }
|
||||||
|
|
||||||
|
CompilerLocalVariableToRegisterMappingTable& getFunctionVariableMappingTable() { return gFunctionVariableMappingTable; }
|
||||||
|
|
||||||
void setCurrentStringTable(CompilerStringTable* cst) { gCurrentStringTable = cst; }
|
void setCurrentStringTable(CompilerStringTable* cst) { gCurrentStringTable = cst; }
|
||||||
|
|
||||||
CompilerFloatTable *getCurrentFloatTable() { return gCurrentFloatTable; }
|
CompilerFloatTable *getCurrentFloatTable() { return gCurrentFloatTable; }
|
||||||
|
|
@ -117,6 +120,7 @@ namespace Compiler
|
||||||
getFunctionFloatTable().reset();
|
getFunctionFloatTable().reset();
|
||||||
getFunctionStringTable().reset();
|
getFunctionStringTable().reset();
|
||||||
getIdentTable().reset();
|
getIdentTable().reset();
|
||||||
|
getFunctionVariableMappingTable().reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void *consoleAlloc(U32 size) { return gConsoleAllocator.alloc(size); }
|
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)
|
U32 CompilerFloatTable::add(F64 value)
|
||||||
{
|
{
|
||||||
Entry **walk;
|
Entry **walk;
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,8 @@ class DataChunker;
|
||||||
#include "core/util/tVector.h"
|
#include "core/util/tVector.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//------------------------------------------------------------
|
||||||
|
|
||||||
namespace Compiler
|
namespace Compiler
|
||||||
{
|
{
|
||||||
/// The opcodes for the TorqueScript VM.
|
/// The opcodes for the TorqueScript VM.
|
||||||
|
|
@ -252,6 +254,7 @@ namespace Compiler
|
||||||
CompilerStringTable *getCurrentStringTable();
|
CompilerStringTable *getCurrentStringTable();
|
||||||
CompilerStringTable &getGlobalStringTable();
|
CompilerStringTable &getGlobalStringTable();
|
||||||
CompilerStringTable &getFunctionStringTable();
|
CompilerStringTable &getFunctionStringTable();
|
||||||
|
CompilerLocalVariableToRegisterMappingTable& getFunctionVariableMappingTable();
|
||||||
|
|
||||||
void setCurrentStringTable(CompilerStringTable* cst);
|
void setCurrentStringTable(CompilerStringTable* cst);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -644,6 +644,11 @@ public:
|
||||||
return *(stack[mStackDepth - 1]);
|
return *(stack[mStackDepth - 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Dictionary& getFrameAt(S32 depth)
|
||||||
|
{
|
||||||
|
return *(stack[depth]);
|
||||||
|
}
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
/// Run integrity checks for debugging.
|
/// Run integrity checks for debugging.
|
||||||
|
|
|
||||||
|
|
@ -864,6 +864,37 @@ void TelnetDebugger::evaluateExpression(const char *tag, S32 frame, const char *
|
||||||
if ( frame < 0 )
|
if ( frame < 0 )
|
||||||
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.
|
// Build a buffer just big enough for this eval.
|
||||||
const char* format = "return %s;";
|
const char* format = "return %s;";
|
||||||
dsize_t len = dStrlen( format ) + dStrlen( evalBuffer );
|
dsize_t len = dStrlen( format ) + dStrlen( evalBuffer );
|
||||||
|
|
@ -872,14 +903,14 @@ void TelnetDebugger::evaluateExpression(const char *tag, S32 frame, const char *
|
||||||
|
|
||||||
// Execute the eval.
|
// Execute the eval.
|
||||||
CodeBlock *newCodeBlock = new CodeBlock();
|
CodeBlock *newCodeBlock = new CodeBlock();
|
||||||
const char* result = newCodeBlock->compileExec( NULL, buffer, false, frame );
|
ConsoleValue result = newCodeBlock->compileExec( NULL, buffer, false, frame );
|
||||||
delete [] buffer;
|
delete [] buffer;
|
||||||
|
|
||||||
// Create a new buffer that fits the result.
|
// Create a new buffer that fits the result.
|
||||||
format = "EVALOUT %s %s\r\n";
|
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 ];
|
buffer = new char[ len ];
|
||||||
dSprintf( buffer, len, format, tag, result[0] ? result : "\"\"" );
|
dSprintf( buffer, len, format, tag, result.getString()[0] ? result.getString() : "\"\"" );
|
||||||
|
|
||||||
send( buffer );
|
send( buffer );
|
||||||
delete [] buffer;
|
delete [] buffer;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue