From 1e4458660602ddb95308ba7cbcab43952a611caa Mon Sep 17 00:00:00 2001 From: James Urquhart Date: Sun, 7 Sep 2014 17:38:35 +0100 Subject: [PATCH 1/6] Refactor TS compiler to not use the precompile step & also 64bit support - Reduces headaches - Expands STE entry size to allow for 64bit values - Bonus: Adds in function lookup optimization from T2D --- Engine/source/console/ast.h | 150 ++- Engine/source/console/astNodes.cpp | 1179 ++++++++---------------- Engine/source/console/codeBlock.cpp | 172 ++-- Engine/source/console/codeBlock.h | 1 - Engine/source/console/compiledEval.cpp | 97 +- Engine/source/console/compiler.cpp | 154 +++- Engine/source/console/compiler.h | 210 ++++- Engine/source/console/console.h | 3 +- 8 files changed, 957 insertions(+), 1009 deletions(-) diff --git a/Engine/source/console/ast.h b/Engine/source/console/ast.h index 4be4fef90..45126e2b4 100644 --- a/Engine/source/console/ast.h +++ b/Engine/source/console/ast.h @@ -27,6 +27,7 @@ class ExprEvalState; class Namespace; class SimObject; class SimGroup; +class CodeStream; /// Enable this #define if you are seeing the message "precompile size mismatch" in the console. /// This will help track down which node type is causing the error. It could be @@ -77,15 +78,13 @@ struct StmtNode /// @name Breaking /// @{ - void addBreakCount(); - void addBreakLine(U32 ip); + void addBreakLine(CodeStream &codeStream); /// @} /// @name Compilation /// @{ - virtual U32 precompileStmt(U32 loopCount) = 0; - virtual U32 compileStmt(U32 *codeStream, U32 ip, U32 continuePoint, U32 breakPoint) = 0; + virtual U32 compileStmt(CodeStream &codeStream, U32 ip) = 0; virtual void setPackage(StringTableEntry packageName); /// @} }; @@ -101,27 +100,26 @@ struct BreakStmtNode : StmtNode { static BreakStmtNode *alloc( S32 lineNumber ); - U32 precompileStmt(U32 loopCount); - U32 compileStmt(U32 *codeStream, U32 ip, U32 continuePoint, U32 breakPoint); + + U32 compileStmt(CodeStream &codeStream, U32 ip); DBG_STMT_TYPE(BreakStmtNode); }; struct ContinueStmtNode : StmtNode { static ContinueStmtNode *alloc( S32 lineNumber ); - U32 precompileStmt(U32 loopCount); - U32 compileStmt(U32 *codeStream, U32 ip, U32 continuePoint, U32 breakPoint); + + U32 compileStmt(CodeStream &codeStream, U32 ip); DBG_STMT_TYPE(ContinueStmtNode); }; /// A mathematical expression. struct ExprNode : StmtNode { - U32 precompileStmt(U32 loopCount); - U32 compileStmt(U32 *codeStream, U32 ip, U32 continuePoint, U32 breakPoint); + + U32 compileStmt(CodeStream &codeStream, U32 ip); - virtual U32 precompile(TypeReq type) = 0; - virtual U32 compile(U32 *codeStream, U32 ip, TypeReq type) = 0; + virtual U32 compile(CodeStream &codeStream, U32 ip, TypeReq type) = 0; virtual TypeReq getPreferredType() = 0; }; @@ -130,8 +128,8 @@ struct ReturnStmtNode : StmtNode ExprNode *expr; static ReturnStmtNode *alloc( S32 lineNumber, ExprNode *expr ); - U32 precompileStmt(U32 loopCount); - U32 compileStmt(U32 *codeStream, U32 ip, U32 continuePoint, U32 breakPoint); + + U32 compileStmt(CodeStream &codeStream, U32 ip); DBG_STMT_TYPE(ReturnStmtNode); }; @@ -147,8 +145,8 @@ struct IfStmtNode : StmtNode static IfStmtNode *alloc( S32 lineNumber, ExprNode *testExpr, StmtNode *ifBlock, StmtNode *elseBlock, bool propagateThrough ); void propagateSwitchExpr(ExprNode *left, bool string); ExprNode *getSwitchOR(ExprNode *left, ExprNode *list, bool string); - U32 precompileStmt(U32 loopCount); - U32 compileStmt(U32 *codeStream, U32 ip, U32 continuePoint, U32 breakPoint); + + U32 compileStmt(CodeStream &codeStream, U32 ip); DBG_STMT_TYPE(IfStmtNode); }; @@ -165,8 +163,8 @@ struct LoopStmtNode : StmtNode bool integer; static LoopStmtNode *alloc( S32 lineNumber, ExprNode *testExpr, ExprNode *initExpr, ExprNode *endLoopExpr, StmtNode *loopBlock, bool isDoLoop ); - U32 precompileStmt(U32 loopCount); - U32 compileStmt(U32 *codeStream, U32 ip, U32 continuePoint, U32 breakPoint); + + U32 compileStmt(CodeStream &codeStream, U32 ip); DBG_STMT_TYPE(LoopStmtNode); }; @@ -190,8 +188,7 @@ struct IterStmtNode : StmtNode static IterStmtNode* alloc( S32 lineNumber, StringTableEntry varName, ExprNode* containerExpr, StmtNode* body, bool isStringIter ); - U32 precompileStmt( U32 loopCount ); - U32 compileStmt( U32* codeStream, U32 ip, U32 continuePoint, U32 breakPoint ); + U32 compileStmt( CodeStream &codeStream, U32 ip ); }; /// A binary mathematical expression (ie, left op right). @@ -205,8 +202,8 @@ struct BinaryExprNode : ExprNode struct FloatBinaryExprNode : BinaryExprNode { static FloatBinaryExprNode *alloc( S32 lineNumber, S32 op, ExprNode *left, ExprNode *right ); - U32 precompile(TypeReq type); - U32 compile(U32 *codeStream, U32 ip, TypeReq type); + + U32 compile(CodeStream &codeStream, U32 ip, TypeReq type); TypeReq getPreferredType(); DBG_STMT_TYPE(FloatBinaryExprNode); }; @@ -218,8 +215,8 @@ struct ConditionalExprNode : ExprNode ExprNode *falseExpr; bool integer; static ConditionalExprNode *alloc( S32 lineNumber, ExprNode *testExpr, ExprNode *trueExpr, ExprNode *falseExpr ); - virtual U32 precompile(TypeReq type); - virtual U32 compile(U32 *codeStream, U32 ip, TypeReq type); + + virtual U32 compile(CodeStream &codeStream, U32 ip, TypeReq type); virtual TypeReq getPreferredType(); DBG_STMT_TYPE(ConditionalExprNode); }; @@ -232,8 +229,8 @@ struct IntBinaryExprNode : BinaryExprNode static IntBinaryExprNode *alloc( S32 lineNumber, S32 op, ExprNode *left, ExprNode *right ); void getSubTypeOperand(); - U32 precompile(TypeReq type); - U32 compile(U32 *codeStream, U32 ip, TypeReq type); + + U32 compile(CodeStream &codeStream, U32 ip, TypeReq type); TypeReq getPreferredType(); DBG_STMT_TYPE(IntBinaryExprNode); }; @@ -242,8 +239,8 @@ struct StreqExprNode : BinaryExprNode { bool eq; static StreqExprNode *alloc( S32 lineNumber, ExprNode *left, ExprNode *right, bool eq ); - U32 precompile(TypeReq type); - U32 compile(U32 *codeStream, U32 ip, TypeReq type); + + U32 compile(CodeStream &codeStream, U32 ip, TypeReq type); TypeReq getPreferredType(); DBG_STMT_TYPE(StreqExprNode); }; @@ -252,8 +249,8 @@ struct StrcatExprNode : BinaryExprNode { S32 appendChar; static StrcatExprNode *alloc( S32 lineNumber, ExprNode *left, ExprNode *right, S32 appendChar ); - U32 precompile(TypeReq type); - U32 compile(U32 *codeStream, U32 ip, TypeReq type); + + U32 compile(CodeStream &codeStream, U32 ip, TypeReq type); TypeReq getPreferredType(); DBG_STMT_TYPE(StrcatExprNode); }; @@ -262,8 +259,8 @@ struct CommaCatExprNode : BinaryExprNode { static CommaCatExprNode *alloc( S32 lineNumber, ExprNode *left, ExprNode *right ); - U32 precompile(TypeReq type); - U32 compile(U32 *codeStream, U32 ip, TypeReq type); + + U32 compile(CodeStream &codeStream, U32 ip, TypeReq type); TypeReq getPreferredType(); DBG_STMT_TYPE(CommaCatExprNode); }; @@ -275,8 +272,8 @@ struct IntUnaryExprNode : ExprNode bool integer; static IntUnaryExprNode *alloc( S32 lineNumber, S32 op, ExprNode *expr ); - U32 precompile(TypeReq type); - U32 compile(U32 *codeStream, U32 ip, TypeReq type); + + U32 compile(CodeStream &codeStream, U32 ip, TypeReq type); TypeReq getPreferredType(); DBG_STMT_TYPE(IntUnaryExprNode); }; @@ -287,8 +284,8 @@ struct FloatUnaryExprNode : ExprNode ExprNode *expr; static FloatUnaryExprNode *alloc( S32 lineNumber, S32 op, ExprNode *expr ); - U32 precompile(TypeReq type); - U32 compile(U32 *codeStream, U32 ip, TypeReq type); + + U32 compile(CodeStream &codeStream, U32 ip, TypeReq type); TypeReq getPreferredType(); DBG_STMT_TYPE(FloatUnaryExprNode); }; @@ -299,8 +296,8 @@ struct VarNode : ExprNode ExprNode *arrayIndex; static VarNode *alloc( S32 lineNumber, StringTableEntry varName, ExprNode *arrayIndex ); - U32 precompile(TypeReq type); - U32 compile(U32 *codeStream, U32 ip, TypeReq type); + + U32 compile(CodeStream &codeStream, U32 ip, TypeReq type); TypeReq getPreferredType(); DBG_STMT_TYPE(VarNode); }; @@ -311,8 +308,8 @@ struct IntNode : ExprNode U32 index; // if it's converted to float/string static IntNode *alloc( S32 lineNumber, S32 value ); - U32 precompile(TypeReq type); - U32 compile(U32 *codeStream, U32 ip, TypeReq type); + + U32 compile(CodeStream &codeStream, U32 ip, TypeReq type); TypeReq getPreferredType(); DBG_STMT_TYPE(IntNode); }; @@ -323,8 +320,8 @@ struct FloatNode : ExprNode U32 index; static FloatNode *alloc( S32 lineNumber, F64 value ); - U32 precompile(TypeReq type); - U32 compile(U32 *codeStream, U32 ip, TypeReq type); + + U32 compile(CodeStream &codeStream, U32 ip, TypeReq type); TypeReq getPreferredType(); DBG_STMT_TYPE(FloatNode); }; @@ -338,8 +335,8 @@ struct StrConstNode : ExprNode bool doc; // Specifies that this string is a documentation block. static StrConstNode *alloc( S32 lineNumber, char *str, bool tag, bool doc = false ); - U32 precompile(TypeReq type); - U32 compile(U32 *codeStream, U32 ip, TypeReq type); + + U32 compile(CodeStream &codeStream, U32 ip, TypeReq type); TypeReq getPreferredType(); DBG_STMT_TYPE(StrConstNode); }; @@ -351,8 +348,8 @@ struct ConstantNode : ExprNode U32 index; static ConstantNode *alloc( S32 lineNumber, StringTableEntry value ); - U32 precompile(TypeReq type); - U32 compile(U32 *codeStream, U32 ip, TypeReq type); + + U32 compile(CodeStream &codeStream, U32 ip, TypeReq type); TypeReq getPreferredType(); DBG_STMT_TYPE(ConstantNode); }; @@ -365,8 +362,8 @@ struct AssignExprNode : ExprNode TypeReq subType; static AssignExprNode *alloc( S32 lineNumber, StringTableEntry varName, ExprNode *arrayIndex, ExprNode *expr ); - U32 precompile(TypeReq type); - U32 compile(U32 *codeStream, U32 ip, TypeReq type); + + U32 compile(CodeStream &codeStream, U32 ip, TypeReq type); TypeReq getPreferredType(); DBG_STMT_TYPE(AssignExprNode); }; @@ -389,8 +386,8 @@ struct AssignOpExprNode : ExprNode TypeReq subType; static AssignOpExprNode *alloc( S32 lineNumber, StringTableEntry varName, ExprNode *arrayIndex, ExprNode *expr, S32 op ); - U32 precompile(TypeReq type); - U32 compile(U32 *codeStream, U32 ip, TypeReq type); + + U32 compile(CodeStream &codeStream, U32 ip, TypeReq type); TypeReq getPreferredType(); DBG_STMT_TYPE(AssignOpExprNode); }; @@ -402,8 +399,8 @@ struct TTagSetStmtNode : StmtNode ExprNode *stringExpr; static TTagSetStmtNode *alloc( S32 lineNumber, StringTableEntry tag, ExprNode *valueExpr, ExprNode *stringExpr ); - U32 precompileStmt(U32 loopCount); - U32 compileStmt(U32 *codeStream, U32 ip, U32 continuePoint, U32 breakPoint); + + U32 compileStmt(CodeStream &codeStream, U32 ip); DBG_STMT_TYPE(TTagSetStmtNode); }; @@ -412,8 +409,8 @@ struct TTagDerefNode : ExprNode ExprNode *expr; static TTagDerefNode *alloc( S32 lineNumber, ExprNode *expr ); - U32 precompile(TypeReq type); - U32 compile(U32 *codeStream, U32 ip, TypeReq type); + + U32 compile(CodeStream &codeStream, U32 ip, TypeReq type); TypeReq getPreferredType(); DBG_STMT_TYPE(TTagDerefNode); }; @@ -423,8 +420,8 @@ struct TTagExprNode : ExprNode StringTableEntry tag; static TTagExprNode *alloc( S32 lineNumber, StringTableEntry tag ); - U32 precompile(TypeReq type); - U32 compile(U32 *codeStream, U32 ip, TypeReq type); + + U32 compile(CodeStream &codeStream, U32 ip, TypeReq type); TypeReq getPreferredType(); DBG_STMT_TYPE(TTagExprNode); }; @@ -442,8 +439,8 @@ struct FuncCallExprNode : ExprNode }; static FuncCallExprNode *alloc( S32 lineNumber, StringTableEntry funcName, StringTableEntry nameSpace, ExprNode *args, bool dot ); - U32 precompile(TypeReq type); - U32 compile(U32 *codeStream, U32 ip, TypeReq type); + + U32 compile(CodeStream &codeStream, U32 ip, TypeReq type); TypeReq getPreferredType(); DBG_STMT_TYPE(FuncCallExprNode); }; @@ -455,8 +452,8 @@ struct AssertCallExprNode : ExprNode U32 messageIndex; static AssertCallExprNode *alloc( S32 lineNumber, ExprNode *testExpr, const char *message ); - U32 precompile(TypeReq type); - U32 compile(U32 *codeStream, U32 ip, TypeReq type); + + U32 compile(CodeStream &codeStream, U32 ip, TypeReq type); TypeReq getPreferredType(); DBG_STMT_TYPE(AssertCallExprNode); }; @@ -475,8 +472,8 @@ struct SlotAccessNode : ExprNode StringTableEntry slotName; static SlotAccessNode *alloc( S32 lineNumber, ExprNode *objectExpr, ExprNode *arrayExpr, StringTableEntry slotName ); - U32 precompile(TypeReq type); - U32 compile(U32 *codeStream, U32 ip, TypeReq type); + + U32 compile(CodeStream &codeStream, U32 ip, TypeReq type); TypeReq getPreferredType(); DBG_STMT_TYPE(SlotAccessNode); }; @@ -495,8 +492,8 @@ struct InternalSlotAccessNode : ExprNode bool recurse; static InternalSlotAccessNode *alloc( S32 lineNumber, ExprNode *objectExpr, ExprNode *slotExpr, bool recurse ); - U32 precompile(TypeReq type); - U32 compile(U32 *codeStream, U32 ip, TypeReq type); + + U32 compile(CodeStream &codeStream, U32 ip, TypeReq type); TypeReq getPreferredType(); DBG_STMT_TYPE(InternalSlotAccessNode); }; @@ -509,8 +506,8 @@ struct SlotAssignNode : ExprNode U32 typeID; static SlotAssignNode *alloc( S32 lineNumber, ExprNode *objectExpr, ExprNode *arrayExpr, StringTableEntry slotName, ExprNode *valueExpr, U32 typeID = -1 ); - U32 precompile(TypeReq type); - U32 compile(U32 *codeStream, U32 ip, TypeReq type); + + U32 compile(CodeStream &codeStream, U32 ip, TypeReq type); TypeReq getPreferredType(); DBG_STMT_TYPE(SlotAssignNode); }; @@ -525,8 +522,8 @@ struct SlotAssignOpNode : ExprNode TypeReq subType; static SlotAssignOpNode *alloc( S32 lineNumber, ExprNode *objectExpr, StringTableEntry slotName, ExprNode *arrayExpr, S32 op, ExprNode *valueExpr ); - U32 precompile(TypeReq type); - U32 compile(U32 *codeStream, U32 ip, TypeReq type); + + U32 compile(CodeStream &codeStream, U32 ip, TypeReq type); TypeReq getPreferredType(); DBG_STMT_TYPE(SlotAssignOpNode); }; @@ -545,10 +542,10 @@ struct ObjectDeclNode : ExprNode bool isSingleton; static ObjectDeclNode *alloc( S32 lineNumber, ExprNode *classNameExpr, ExprNode *objectNameExpr, ExprNode *argList, StringTableEntry parentObject, SlotAssignNode *slotDecls, ObjectDeclNode *subObjects, bool isDatablock, bool classNameInternal, bool isSingleton ); - U32 precompile(TypeReq type); + U32 precompileSubObject(bool); - U32 compile(U32 *codeStream, U32 ip, TypeReq type); - U32 compileSubObject(U32 *codeStream, U32 ip, bool); + U32 compile(CodeStream &codeStream, U32 ip, TypeReq type); + U32 compileSubObject(CodeStream &codeStream, U32 ip, bool); TypeReq getPreferredType(); DBG_STMT_TYPE(ObjectDeclNode); }; @@ -570,18 +567,13 @@ struct FunctionDeclStmtNode : StmtNode U32 argc; static FunctionDeclStmtNode *alloc( S32 lineNumber, StringTableEntry fnName, StringTableEntry nameSpace, VarNode *args, StmtNode *stmts ); - U32 precompileStmt(U32 loopCount); - U32 compileStmt(U32 *codeStream, U32 ip, U32 continuePoint, U32 breakPoint); + + U32 compileStmt(CodeStream &codeStream, U32 ip); void setPackage(StringTableEntry packageName); DBG_STMT_TYPE(FunctionDeclStmtNode); }; extern StmtNode *gStatementList; -extern void createFunction(const char *fnName, VarNode *args, StmtNode *statements); -extern ExprEvalState gEvalState; -extern bool lookupFunction(const char *fnName, VarNode **args, StmtNode **statements); -typedef const char *(*cfunc)(S32 argc, char **argv); -extern bool lookupCFunction(const char *fnName, cfunc *f); - +extern ExprEvalState gEvalState;; #endif diff --git a/Engine/source/console/astNodes.cpp b/Engine/source/console/astNodes.cpp index 11cc44f90..666589f6a 100644 --- a/Engine/source/console/astNodes.cpp +++ b/Engine/source/console/astNodes.cpp @@ -45,26 +45,11 @@ struct Token namespace Compiler { - U32 precompileBlock(StmtNode *block, U32 loopCount) - { - U32 sum = 0; - for(StmtNode *walk = block; walk; walk = walk->getNext()) - { - const U32 temp = walk->precompileStmt(loopCount); -#ifdef DEBUG_AST_NODES - if(temp > 1000) - Con::printf("suspect %s '%s' line %d", walk->dbgStmtType().c_str(), walk->dbgFileName, walk->dbgLineNumber); -#endif - sum += temp; - } - return sum; - } - - U32 compileBlock(StmtNode *block, U32 *codeStream, U32 ip, U32 continuePoint, U32 breakPoint) + U32 compileBlock(StmtNode *block, CodeStream &codeStream, U32 ip) { for(StmtNode *walk = block; walk; walk = walk->getNext()) - ip = walk->compileStmt(codeStream, ip, continuePoint, breakPoint); - return ip; + ip = walk->compileStmt(codeStream, ip); + return codeStream.tell(); } } @@ -72,21 +57,9 @@ using namespace Compiler; //----------------------------------------------------------------------------- -void StmtNode::addBreakCount() +void StmtNode::addBreakLine(CodeStream &code) { - CodeBlock::smBreakLineCount++; -} - -void StmtNode::addBreakLine(U32 ip) -{ - U32 line = CodeBlock::smBreakLineCount * 2; - CodeBlock::smBreakLineCount++; - - if(getBreakCodeBlock()->lineBreakPairs) - { - getBreakCodeBlock()->lineBreakPairs[line] = dbgLineNumber; - getBreakCodeBlock()->lineBreakPairs[line+1] = ip; - } + code.addBreakLine(dbgLineNumber, code.tell()); } //------------------------------------------------------------ @@ -170,85 +143,59 @@ static U32 conversionOp(TypeReq src, TypeReq dst) //------------------------------------------------------------ -U32 BreakStmtNode::precompileStmt(U32 loopCount) +U32 BreakStmtNode::compileStmt(CodeStream &codeStream, U32 ip) { - if(loopCount) + if(codeStream.inLoop()) { - addBreakCount(); - return 2; + addBreakLine(codeStream); + codeStream.emit(OP_JMP); + codeStream.emitFix(CodeStream::FIXTYPE_BREAK); } - Con::warnf(ConsoleLogEntry::General, "%s (%d): break outside of loop... ignoring.", dbgFileName, dbgLineNumber); - return 0; -} - -U32 BreakStmtNode::compileStmt(U32 *codeStream, U32 ip, U32, U32 breakPoint) -{ - if(breakPoint) + else { - addBreakLine(ip); - codeStream[ip++] = OP_JMP; - codeStream[ip++] = breakPoint; + Con::warnf(ConsoleLogEntry::General, "%s (%d): break outside of loop... ignoring.", dbgFileName, dbgLineNumber); } - return ip; + return codeStream.tell(); } //------------------------------------------------------------ -U32 ContinueStmtNode::precompileStmt(U32 loopCount) +U32 ContinueStmtNode::compileStmt(CodeStream &codeStream, U32 ip) { - if(loopCount) + if(codeStream.inLoop()) { - addBreakCount(); - return 2; + addBreakLine(codeStream); + codeStream.emit(OP_JMP); + codeStream.emitFix(CodeStream::FIXTYPE_CONTINUE); } - Con::warnf(ConsoleLogEntry::General, "%s (%d): continue outside of loop... ignoring.", dbgFileName, dbgLineNumber); - return 0; -} - -U32 ContinueStmtNode::compileStmt(U32 *codeStream, U32 ip, U32 continuePoint, U32) -{ - if(continuePoint) + else { - addBreakLine(ip); - codeStream[ip++] = OP_JMP; - codeStream[ip++] = continuePoint; + Con::warnf(ConsoleLogEntry::General, "%s (%d): continue outside of loop... ignoring.", dbgFileName, dbgLineNumber); } - return ip; + return codeStream.tell(); } //------------------------------------------------------------ -U32 ExprNode::precompileStmt(U32) +U32 ExprNode::compileStmt(CodeStream &codeStream, U32 ip) { - addBreakCount(); - return precompile(TypeReqNone); -} - -U32 ExprNode::compileStmt(U32 *codeStream, U32 ip, U32, U32) -{ - addBreakLine(ip); + addBreakLine(codeStream); return compile(codeStream, ip, TypeReqNone); } //------------------------------------------------------------ -U32 ReturnStmtNode::precompileStmt(U32) +U32 ReturnStmtNode::compileStmt(CodeStream &codeStream, U32 ip) { - addBreakCount(); - return 1 + (expr ? expr->precompile(TypeReqString) : 0); -} - -U32 ReturnStmtNode::compileStmt(U32 *codeStream, U32 ip, U32, U32) -{ - addBreakLine(ip); + addBreakLine(codeStream); if(!expr) - codeStream[ip++] = OP_RETURN_VOID; + codeStream.emit(OP_RETURN_VOID); else { ip = expr->compile(codeStream, ip, TypeReqString); - codeStream[ip++] = OP_RETURN; + codeStream.emit(OP_RETURN); } - return ip; + return codeStream.tell(); } //------------------------------------------------------------ @@ -273,87 +220,60 @@ void IfStmtNode::propagateSwitchExpr(ExprNode *left, bool string) ((IfStmtNode *) elseBlock)->propagateSwitchExpr(left, string); } -U32 IfStmtNode::precompileStmt(U32 loopCount) +U32 IfStmtNode::compileStmt(CodeStream &codeStream, U32 ip) { - U32 exprSize; - addBreakCount(); - + U32 start = ip; + U32 endifIp, elseIp; + addBreakLine(codeStream); + if(testExpr->getPreferredType() == TypeReqUInt) { - exprSize = testExpr->precompile(TypeReqUInt); integer = true; } else { - exprSize = testExpr->precompile(TypeReqFloat); integer = false; } - // next is the JMPIFNOT or JMPIFFNOT - size of 2 - U32 ifSize = precompileBlock(ifBlock, loopCount); - if(!elseBlock) - endifOffset = ifSize + 2 + exprSize; - else - { - elseOffset = exprSize + 2 + ifSize + 2; - U32 elseSize = precompileBlock(elseBlock, loopCount); - endifOffset = elseOffset + elseSize; - } - return endifOffset; -} - -U32 IfStmtNode::compileStmt(U32 *codeStream, U32 ip, U32 continuePoint, U32 breakPoint) -{ - U32 start = ip; - addBreakLine(ip); ip = testExpr->compile(codeStream, ip, integer ? TypeReqUInt : TypeReqFloat); - codeStream[ip++] = integer ? OP_JMPIFNOT : OP_JMPIFFNOT; + codeStream.emit(integer ? OP_JMPIFNOT : OP_JMPIFFNOT); if(elseBlock) { - codeStream[ip++] = start + elseOffset; - ip = compileBlock(ifBlock, codeStream, ip, continuePoint, breakPoint); - codeStream[ip++] = OP_JMP; - codeStream[ip++] = start + endifOffset; - ip = compileBlock(elseBlock, codeStream, ip, continuePoint, breakPoint); + elseIp = codeStream.emit(0); + elseOffset = compileBlock(ifBlock, codeStream, ip) + 2; + codeStream.emit(OP_JMP); + endifIp = codeStream.emit(0); + endifOffset = compileBlock(elseBlock, codeStream, ip); + + codeStream.patch(endifIp, endifOffset); + codeStream.patch(elseIp, elseOffset); } else { - codeStream[ip++] = start + endifOffset; - ip = compileBlock(ifBlock, codeStream, ip, continuePoint, breakPoint); + endifIp = codeStream.emit(0); + endifOffset = compileBlock(ifBlock, codeStream, ip); + + codeStream.patch(endifIp, endifOffset); } - return ip; + + // Resolve fixes + return codeStream.tell(); } //------------------------------------------------------------ -U32 LoopStmtNode::precompileStmt(U32 loopCount) +U32 LoopStmtNode::compileStmt(CodeStream &codeStream, U32 ip) { - U32 initSize = 0; - addBreakCount(); - - if(initExpr) - initSize = initExpr->precompile(TypeReqNone); - - U32 testSize; - if(testExpr->getPreferredType() == TypeReqUInt) { integer = true; - testSize = testExpr->precompile(TypeReqUInt); } else { integer = false; - testSize = testExpr->precompile(TypeReqFloat); } - - U32 blockSize = precompileBlock(loopBlock, loopCount + 1); - - U32 endLoopSize = 0; - if(endLoopExpr) - endLoopSize = endLoopExpr->precompile(TypeReqNone); - + // if it's a for loop or a while loop it goes: // initExpr // testExpr @@ -365,7 +285,7 @@ U32 LoopStmtNode::precompileStmt(U32 loopCount) // testExpr // OP_JMPIF loopStartPoint // breakPoint: - + // otherwise if it's a do ... while() it goes: // initExpr // loopStartPoint: @@ -375,25 +295,15 @@ U32 LoopStmtNode::precompileStmt(U32 loopCount) // testExpr // OP_JMPIF loopStartPoint // breakPoint: - - if(!isDoLoop) - { - loopBlockStartOffset = initSize + testSize + 2; - continueOffset = loopBlockStartOffset + blockSize; - breakOffset = continueOffset + endLoopSize + testSize + 2; - } - else - { - loopBlockStartOffset = initSize; - continueOffset = initSize + blockSize; - breakOffset = continueOffset + endLoopSize + testSize + 2; - } - return breakOffset; -} - -U32 LoopStmtNode::compileStmt(U32 *codeStream, U32 ip, U32, U32) -{ - addBreakLine(ip); + + // loopBlockStart == start of loop block + // continue == skip to end + // break == exit loop + + + addBreakLine(codeStream); + codeStream.pushFixScope(true); + U32 start = ip; if(initExpr) ip = initExpr->compile(codeStream, ip, TypeReqNone); @@ -401,30 +311,34 @@ U32 LoopStmtNode::compileStmt(U32 *codeStream, U32 ip, U32, U32) if(!isDoLoop) { ip = testExpr->compile(codeStream, ip, integer ? TypeReqUInt : TypeReqFloat); - codeStream[ip++] = integer ? OP_JMPIFNOT : OP_JMPIFFNOT; - codeStream[ip++] = start + breakOffset; + codeStream.emit(integer ? OP_JMPIFNOT : OP_JMPIFFNOT); + codeStream.emitFix(CodeStream::FIXTYPE_BREAK); } // Compile internals of loop. - ip = compileBlock(loopBlock, codeStream, ip, start + continueOffset, start + breakOffset); + loopBlockStartOffset = codeStream.tell(); + continueOffset = compileBlock(loopBlock, codeStream, ip); if(endLoopExpr) ip = endLoopExpr->compile(codeStream, ip, TypeReqNone); ip = testExpr->compile(codeStream, ip, integer ? TypeReqUInt : TypeReqFloat); - codeStream[ip++] = integer ? OP_JMPIF : OP_JMPIFF; - codeStream[ip++] = start + loopBlockStartOffset; - - return ip; + codeStream.emit(integer ? OP_JMPIF : OP_JMPIFF); + codeStream.emitFix(CodeStream::FIXTYPE_LOOPBLOCKSTART); + + breakOffset = codeStream.tell(); // exit loop + + codeStream.fixLoop(loopBlockStartOffset, breakOffset, continueOffset); + codeStream.popFixScope(); + + return codeStream.tell(); } //------------------------------------------------------------ -U32 IterStmtNode::precompileStmt( U32 loopCount ) +U32 IterStmtNode::compileStmt( CodeStream &codeStream, U32 ip ) { - addBreakCount(); - // Instruction sequence: // // containerExpr @@ -436,86 +350,66 @@ U32 IterStmtNode::precompileStmt( U32 loopCount ) // .break: // OP_ITER_END // .fail: - - U32 exprSize = containerExpr->precompile( TypeReqString ); - bodySize = precompileBlock( body, loopCount + 1 ); - return - exprSize - + 3 // OP_ITER_BEGIN - + 2 // OP_ITER - + bodySize - + 2 // OP_JMP - + 1 // OP_ITER_END - ; -} - -U32 IterStmtNode::compileStmt( U32* codeStream, U32 ip, U32 continuePoint, U32 breakPoint ) -{ - addBreakLine( ip ); + addBreakLine(codeStream); + + codeStream.pushFixScope(true); const U32 startIp = ip; - const U32 iterBeginIp = containerExpr->compile( codeStream, startIp, TypeReqString ); - - const U32 continueIp = iterBeginIp + 3; - const U32 bodyIp = continueIp + 2; - const U32 jmpIp = bodyIp + bodySize; + containerExpr->compile( codeStream, startIp, TypeReqString ); + + codeStream.emit(isStringIter ? OP_ITER_BEGIN_STR : OP_ITER_BEGIN); + codeStream.emitSTE( varName ); + const U32 finalFix = codeStream.emit(0); + const U32 continueIp = codeStream.emit(OP_ITER); + codeStream.emitFix(CodeStream::FIXTYPE_BREAK); + const U32 bodyIp = codeStream.tell(); + + const U32 jmpIp = compileBlock( body, codeStream, bodyIp); const U32 breakIp = jmpIp + 2; const U32 finalIp = breakIp + 1; - codeStream[ iterBeginIp ] = isStringIter ? OP_ITER_BEGIN_STR : OP_ITER_BEGIN; - codeStream[ iterBeginIp + 1 ] = STEtoU32( varName, iterBeginIp + 1 ); - codeStream[ iterBeginIp + 2 ] = finalIp; - codeStream[ continueIp ] = OP_ITER; - codeStream[ continueIp + 1 ] = breakIp; - - compileBlock( body, codeStream, bodyIp, continueIp, breakIp ); + codeStream.emit(OP_JMP); + codeStream.emitFix(CodeStream::FIXTYPE_CONTINUE); + codeStream.emit(OP_ITER_END); - codeStream[ jmpIp ] = OP_JMP; - codeStream[ jmpIp + 1 ] = continueIp; - codeStream[ breakIp ] = OP_ITER_END; + codeStream.patch(finalFix, finalIp); + codeStream.fixLoop(bodyIp, breakIp, continueIp); + codeStream.popFixScope(); - return finalIp; + return codeStream.tell(); } //------------------------------------------------------------ -U32 ConditionalExprNode::precompile(TypeReq type) +U32 ConditionalExprNode::compile(CodeStream &codeStream, U32 ip, TypeReq type) { // code is testExpr // JMPIFNOT falseStart // trueExpr // JMP end // falseExpr - U32 exprSize; - if(testExpr->getPreferredType() == TypeReqUInt) { - exprSize = testExpr->precompile(TypeReqUInt); integer = true; } else { - exprSize = testExpr->precompile(TypeReqFloat); integer = false; } - return exprSize + - trueExpr->precompile(type) + - falseExpr->precompile(type) + 4; -} - -U32 ConditionalExprNode::compile(U32 *codeStream, U32 ip, TypeReq type) -{ + ip = testExpr->compile(codeStream, ip, integer ? TypeReqUInt : TypeReqFloat); - codeStream[ip++] = integer ? OP_JMPIFNOT : OP_JMPIFFNOT; - U32 jumpElseIp = ip++; + codeStream.emit(integer ? OP_JMPIFNOT : OP_JMPIFFNOT); + + U32 jumpElseIp = codeStream.emit(0); ip = trueExpr->compile(codeStream, ip, type); - codeStream[ip++] = OP_JMP; - U32 jumpEndIp = ip++; - codeStream[jumpElseIp] = ip; + codeStream.emit(OP_JMP); + U32 jumpEndIp = codeStream.emit(0); + codeStream.patch(jumpElseIp, codeStream.tell()); ip = falseExpr->compile(codeStream, ip, type); - codeStream[jumpEndIp] = ip; - return ip; + codeStream.patch(jumpEndIp, codeStream.tell()); + + return codeStream.tell(); } TypeReq ConditionalExprNode::getPreferredType() @@ -525,16 +419,7 @@ TypeReq ConditionalExprNode::getPreferredType() //------------------------------------------------------------ -U32 FloatBinaryExprNode::precompile(TypeReq type) -{ - U32 addSize = left->precompile(TypeReqFloat) + right->precompile(TypeReqFloat) + 1; - if(type != TypeReqFloat) - addSize++; - - return addSize; -} - -U32 FloatBinaryExprNode::compile(U32 *codeStream, U32 ip, TypeReq type) +U32 FloatBinaryExprNode::compile(CodeStream &codeStream, U32 ip, TypeReq type) { ip = right->compile(codeStream, ip, TypeReqFloat); ip = left->compile(codeStream, ip, TypeReqFloat); @@ -554,10 +439,10 @@ U32 FloatBinaryExprNode::compile(U32 *codeStream, U32 ip, TypeReq type) operand = OP_MUL; break; } - codeStream[ip++] = operand; + codeStream.emit(operand); if(type != TypeReqFloat) - codeStream[ip++] =conversionOp(TypeReqFloat, type); - return ip; + codeStream.emit(conversionOp(TypeReqFloat, type)); + return codeStream.tell(); } TypeReq FloatBinaryExprNode::getPreferredType() @@ -623,38 +508,27 @@ void IntBinaryExprNode::getSubTypeOperand() } } -U32 IntBinaryExprNode::precompile(TypeReq type) +U32 IntBinaryExprNode::compile(CodeStream &codeStream, U32 ip, TypeReq type) { getSubTypeOperand(); - U32 addSize = left->precompile(subType) + right->precompile(subType) + 1; - if(operand == OP_OR || operand == OP_AND) - addSize++; - - if(type != TypeReqUInt) - addSize++; - - return addSize; -} - -U32 IntBinaryExprNode::compile(U32 *codeStream, U32 ip, TypeReq type) -{ + if(operand == OP_OR || operand == OP_AND) { ip = left->compile(codeStream, ip, subType); - codeStream[ip++] = operand == OP_OR ? OP_JMPIF_NP : OP_JMPIFNOT_NP; - U32 jmpIp = ip++; + codeStream.emit(operand == OP_OR ? OP_JMPIF_NP : OP_JMPIFNOT_NP); + U32 jmpIp = codeStream.emit(0); ip = right->compile(codeStream, ip, subType); - codeStream[jmpIp] = ip; + codeStream.patch(jmpIp, ip); } else { ip = right->compile(codeStream, ip, subType); ip = left->compile(codeStream, ip, subType); - codeStream[ip++] = operand; + codeStream.emit(operand); } if(type != TypeReqUInt) - codeStream[ip++] =conversionOp(TypeReqUInt, type); - return ip; + codeStream.emit(conversionOp(TypeReqUInt, type)); + return codeStream.tell(); } TypeReq IntBinaryExprNode::getPreferredType() @@ -664,32 +538,23 @@ TypeReq IntBinaryExprNode::getPreferredType() //------------------------------------------------------------ -U32 StreqExprNode::precompile(TypeReq type) +U32 StreqExprNode::compile(CodeStream &codeStream, U32 ip, TypeReq type) { // eval str left // OP_ADVANCE_STR_NUL // eval str right // OP_COMPARE_STR // optional conversion - U32 addSize = left->precompile(TypeReqString) + right->precompile(TypeReqString) + 2; - if(!eq) - addSize ++; - if(type != TypeReqUInt) - addSize ++; - return addSize; -} - -U32 StreqExprNode::compile(U32 *codeStream, U32 ip, TypeReq type) -{ + ip = left->compile(codeStream, ip, TypeReqString); - codeStream[ip++] = OP_ADVANCE_STR_NUL; + codeStream.emit(OP_ADVANCE_STR_NUL); ip = right->compile(codeStream, ip, TypeReqString); - codeStream[ip++] = OP_COMPARE_STR; + codeStream.emit(OP_COMPARE_STR); if(!eq) - codeStream[ip++] = OP_NOT; + codeStream.emit(OP_NOT); if(type != TypeReqUInt) - codeStream[ip++] = conversionOp(TypeReqUInt, type); - return ip; + codeStream.emit(conversionOp(TypeReqUInt, type)); + return codeStream.tell(); } TypeReq StreqExprNode::getPreferredType() @@ -699,34 +564,23 @@ TypeReq StreqExprNode::getPreferredType() //------------------------------------------------------------ -U32 StrcatExprNode::precompile(TypeReq type) -{ - U32 addSize = left->precompile(TypeReqString) + right->precompile(TypeReqString) + 2; - if(appendChar) - addSize++; - - if(type != TypeReqString) - addSize ++; - return addSize; -} - -U32 StrcatExprNode::compile(U32 *codeStream, U32 ip, TypeReq type) +U32 StrcatExprNode::compile(CodeStream &codeStream, U32 ip, TypeReq type) { ip = left->compile(codeStream, ip, TypeReqString); if(!appendChar) - codeStream[ip++] = OP_ADVANCE_STR; + codeStream.emit(OP_ADVANCE_STR); else { - codeStream[ip++] = OP_ADVANCE_STR_APPENDCHAR; - codeStream[ip++] = appendChar; + codeStream.emit(OP_ADVANCE_STR_APPENDCHAR); + codeStream.emit(appendChar); } ip = right->compile(codeStream, ip, TypeReqString); - codeStream[ip++] = OP_REWIND_STR; + codeStream.emit(OP_REWIND_STR); if(type == TypeReqUInt) - codeStream[ip++] = OP_STR_TO_UINT; + codeStream.emit(OP_STR_TO_UINT); else if(type == TypeReqFloat) - codeStream[ip++] = OP_STR_TO_FLT; - return ip; + codeStream.emit(OP_STR_TO_FLT); + return codeStream.tell(); } TypeReq StrcatExprNode::getPreferredType() @@ -736,20 +590,12 @@ TypeReq StrcatExprNode::getPreferredType() //------------------------------------------------------------ -U32 CommaCatExprNode::precompile(TypeReq type) -{ - U32 addSize = left->precompile(TypeReqString) + right->precompile(TypeReqString) + 2; - if(type != TypeReqString) - addSize ++; - return addSize; -} - -U32 CommaCatExprNode::compile(U32 *codeStream, U32 ip, TypeReq type) +U32 CommaCatExprNode::compile(CodeStream &codeStream, U32 ip, TypeReq type) { ip = left->compile(codeStream, ip, TypeReqString); - codeStream[ip++] = OP_ADVANCE_STR_COMMA; + codeStream.emit(OP_ADVANCE_STR_COMMA); ip = right->compile(codeStream, ip, TypeReqString); - codeStream[ip++] = OP_REWIND_STR; + codeStream.emit(OP_REWIND_STR); // At this point the stack has the concatenated string. @@ -757,10 +603,10 @@ U32 CommaCatExprNode::compile(U32 *codeStream, U32 ip, TypeReq type) if(type == TypeReqUInt || type == TypeReqFloat) Con::warnf(ConsoleLogEntry::General, "%s (%d): converting comma string to a number... probably wrong.", dbgFileName, dbgLineNumber); if(type == TypeReqUInt) - codeStream[ip++] = OP_STR_TO_UINT; + codeStream.emit(OP_STR_TO_UINT); else if(type == TypeReqFloat) - codeStream[ip++] = OP_STR_TO_FLT; - return ip; + codeStream.emit(OP_STR_TO_FLT); + return codeStream.tell(); } TypeReq CommaCatExprNode::getPreferredType() @@ -770,30 +616,21 @@ TypeReq CommaCatExprNode::getPreferredType() //------------------------------------------------------------ -U32 IntUnaryExprNode::precompile(TypeReq type) +U32 IntUnaryExprNode::compile(CodeStream &codeStream, U32 ip, TypeReq type) { integer = true; TypeReq prefType = expr->getPreferredType(); if(op == '!' && (prefType == TypeReqFloat || prefType == TypeReqString)) integer = false; - - U32 exprSize = expr->precompile(integer ? TypeReqUInt : TypeReqFloat); - if(type != TypeReqUInt) - return exprSize + 2; - else - return exprSize + 1; -} - -U32 IntUnaryExprNode::compile(U32 *codeStream, U32 ip, TypeReq type) -{ + ip = expr->compile(codeStream, ip, integer ? TypeReqUInt : TypeReqFloat); if(op == '!') - codeStream[ip++] = integer ? OP_NOT : OP_NOTF; + codeStream.emit(integer ? OP_NOT : OP_NOTF); else if(op == '~') - codeStream[ip++] = OP_ONESCOMPLEMENT; + codeStream.emit(OP_ONESCOMPLEMENT); if(type != TypeReqUInt) - codeStream[ip++] =conversionOp(TypeReqUInt, type); - return ip; + codeStream.emit(conversionOp(TypeReqUInt, type)); + return codeStream.tell(); } TypeReq IntUnaryExprNode::getPreferredType() @@ -803,22 +640,13 @@ TypeReq IntUnaryExprNode::getPreferredType() //------------------------------------------------------------ -U32 FloatUnaryExprNode::precompile(TypeReq type) -{ - U32 exprSize = expr->precompile(TypeReqFloat); - if(type != TypeReqFloat) - return exprSize + 2; - else - return exprSize + 1; -} - -U32 FloatUnaryExprNode::compile(U32 *codeStream, U32 ip, TypeReq type) +U32 FloatUnaryExprNode::compile(CodeStream &codeStream, U32 ip, TypeReq type) { ip = expr->compile(codeStream, ip, TypeReqFloat); - codeStream[ip++] = OP_NEG; + codeStream.emit(OP_NEG); if(type != TypeReqFloat) - codeStream[ip++] =conversionOp(TypeReqFloat, type); - return ip; + codeStream.emit(conversionOp(TypeReqFloat, type)); + return codeStream.tell(); } TypeReq FloatUnaryExprNode::getPreferredType() @@ -828,7 +656,7 @@ TypeReq FloatUnaryExprNode::getPreferredType() //------------------------------------------------------------ -U32 VarNode::precompile(TypeReq type) +U32 VarNode::compile(CodeStream &codeStream, U32 ip, TypeReq type) { // if this has an arrayIndex... // OP_LOADIMMED_IDENT @@ -838,48 +666,42 @@ U32 VarNode::precompile(TypeReq type) // OP_REWIND_STR // OP_SETCURVAR_ARRAY // OP_LOADVAR (type) - + // else // OP_SETCURVAR // varName // OP_LOADVAR (type) + if(type == TypeReqNone) - return 0; - + return codeStream.tell(); + precompileIdent(varName); - return (arrayIndex ? arrayIndex->precompile(TypeReqString) + 6 : 3); -} -U32 VarNode::compile(U32 *codeStream, U32 ip, TypeReq type) -{ - if(type == TypeReqNone) - return ip; - - codeStream[ip++] = arrayIndex ? OP_LOADIMMED_IDENT : OP_SETCURVAR; - codeStream[ip] = STEtoU32(varName, ip); - ip++; + codeStream.emit(arrayIndex ? OP_LOADIMMED_IDENT : OP_SETCURVAR); + codeStream.emitSTE(varName); + if(arrayIndex) { - codeStream[ip++] = OP_ADVANCE_STR; + codeStream.emit(OP_ADVANCE_STR); ip = arrayIndex->compile(codeStream, ip, TypeReqString); - codeStream[ip++] = OP_REWIND_STR; - codeStream[ip++] = OP_SETCURVAR_ARRAY; + codeStream.emit(OP_REWIND_STR); + codeStream.emit(OP_SETCURVAR_ARRAY); } switch(type) { case TypeReqUInt: - codeStream[ip++] = OP_LOADVAR_UINT; + codeStream.emit(OP_LOADVAR_UINT); break; case TypeReqFloat: - codeStream[ip++] = OP_LOADVAR_FLT; + codeStream.emit(OP_LOADVAR_FLT); break; case TypeReqString: - codeStream[ip++] = OP_LOADVAR_STR; + codeStream.emit(OP_LOADVAR_STR); break; case TypeReqNone: break; } - return ip; + return codeStream.tell(); } TypeReq VarNode::getPreferredType() @@ -889,37 +711,31 @@ TypeReq VarNode::getPreferredType() //------------------------------------------------------------ -U32 IntNode::precompile(TypeReq type) +U32 IntNode::compile(CodeStream &codeStream, U32 ip, TypeReq type) { - if(type == TypeReqNone) - return 0; if(type == TypeReqString) index = getCurrentStringTable()->addIntString(value); else if(type == TypeReqFloat) index = getCurrentFloatTable()->add(value); - return 2; -} - -U32 IntNode::compile(U32 *codeStream, U32 ip, TypeReq type) -{ + switch(type) { case TypeReqUInt: - codeStream[ip++] = OP_LOADIMMED_UINT; - codeStream[ip++] = value; + codeStream.emit(OP_LOADIMMED_UINT); + codeStream.emit(value); break; case TypeReqString: - codeStream[ip++] = OP_LOADIMMED_STR; - codeStream[ip++] = index; + codeStream.emit(OP_LOADIMMED_STR); + codeStream.emit(index); break; case TypeReqFloat: - codeStream[ip++] = OP_LOADIMMED_FLT; - codeStream[ip++] = index; + codeStream.emit(OP_LOADIMMED_FLT); + codeStream.emit(index); break; case TypeReqNone: break; } - return ip; + return codeStream.tell(); } TypeReq IntNode::getPreferredType() @@ -929,37 +745,31 @@ TypeReq IntNode::getPreferredType() //------------------------------------------------------------ -U32 FloatNode::precompile(TypeReq type) +U32 FloatNode::compile(CodeStream &codeStream, U32 ip, TypeReq type) { - if(type == TypeReqNone) - return 0; if(type == TypeReqString) index = getCurrentStringTable()->addFloatString(value); else if(type == TypeReqFloat) index = getCurrentFloatTable()->add(value); - return 2; -} - -U32 FloatNode::compile(U32 *codeStream, U32 ip, TypeReq type) -{ + switch(type) { case TypeReqUInt: - codeStream[ip++] = OP_LOADIMMED_UINT; - codeStream[ip++] = U32(value); + codeStream.emit(OP_LOADIMMED_UINT); + codeStream.emit(U32(value)); break; case TypeReqString: - codeStream[ip++] = OP_LOADIMMED_STR; - codeStream[ip++] = index; + codeStream.emit(OP_LOADIMMED_STR); + codeStream.emit(index); break; case TypeReqFloat: - codeStream[ip++] = OP_LOADIMMED_FLT; - codeStream[ip++] = index; + codeStream.emit(OP_LOADIMMED_FLT); + codeStream.emit(index); break; case TypeReqNone: break; } - return ip; + return codeStream.tell(); } TypeReq FloatNode::getPreferredType() @@ -969,38 +779,31 @@ TypeReq FloatNode::getPreferredType() //------------------------------------------------------------ -U32 StrConstNode::precompile(TypeReq type) +U32 StrConstNode::compile(CodeStream &codeStream, U32 ip, TypeReq type) { // Early out for documentation block. if( doc ) { index = getCurrentStringTable()->add(str, true, tag); - return 2; } - - if(type == TypeReqString) + else if(type == TypeReqString) { index = getCurrentStringTable()->add(str, true, tag); - return 2; } - else if(type == TypeReqNone) + else if (type != TypeReqNone) { - return 0; + fVal = consoleStringToNumber(str, dbgFileName, dbgLineNumber); + if(type == TypeReqFloat) + { + index = getCurrentFloatTable()->add(fVal); + } } - - fVal = consoleStringToNumber(str, dbgFileName, dbgLineNumber); - if(type == TypeReqFloat) - index = getCurrentFloatTable()->add(fVal); - return 2; -} - -U32 StrConstNode::compile(U32 *codeStream, U32 ip, TypeReq type) -{ + // If this is a DOCBLOCK, then process w/ appropriate op... if( doc ) { - codeStream[ip++] = OP_DOCBLOCK_STR; - codeStream[ip++] = index; + codeStream.emit(OP_DOCBLOCK_STR); + codeStream.emit(index); return ip; } @@ -1008,21 +811,21 @@ U32 StrConstNode::compile(U32 *codeStream, U32 ip, TypeReq type) switch(type) { case TypeReqString: - codeStream[ip++] = tag ? OP_TAG_TO_STR : OP_LOADIMMED_STR; - codeStream[ip++] = index; + codeStream.emit(tag ? OP_TAG_TO_STR : OP_LOADIMMED_STR); + codeStream.emit(index); break; case TypeReqUInt: - codeStream[ip++] = OP_LOADIMMED_UINT; - codeStream[ip++] = U32(fVal); + codeStream.emit(OP_LOADIMMED_UINT); + codeStream.emit(U32(fVal)); break; case TypeReqFloat: - codeStream[ip++] = OP_LOADIMMED_FLT; - codeStream[ip++] = index; + codeStream.emit(OP_LOADIMMED_FLT); + codeStream.emit(index); break; case TypeReqNone: break; } - return ip; + return codeStream.tell(); } TypeReq StrConstNode::getPreferredType() @@ -1032,38 +835,32 @@ TypeReq StrConstNode::getPreferredType() //------------------------------------------------------------ -U32 ConstantNode::precompile(TypeReq type) +U32 ConstantNode::compile(CodeStream &codeStream, U32 ip, TypeReq type) { if(type == TypeReqString) { precompileIdent(value); - return 2; } - else if(type == TypeReqNone) - return 0; - - fVal = consoleStringToNumber(value, dbgFileName, dbgLineNumber); - if(type == TypeReqFloat) - index = getCurrentFloatTable()->add(fVal); - return 2; -} - -U32 ConstantNode::compile(U32 *codeStream, U32 ip, TypeReq type) -{ + else if (type != TypeReqNone) + { + fVal = consoleStringToNumber(value, dbgFileName, dbgLineNumber); + if(type == TypeReqFloat) + index = getCurrentFloatTable()->add(fVal); + } + switch(type) { case TypeReqString: - codeStream[ip++] = OP_LOADIMMED_IDENT; - codeStream[ip] = STEtoU32(value, ip); - ip++; + codeStream.emit(OP_LOADIMMED_IDENT); + codeStream.emitSTE(value); break; case TypeReqUInt: - codeStream[ip++] = OP_LOADIMMED_UINT; - codeStream[ip++] = U32(fVal); + codeStream.emit(OP_LOADIMMED_UINT); + codeStream.emit(U32(fVal)); break; case TypeReqFloat: - codeStream[ip++] = OP_LOADIMMED_FLT; - codeStream[ip++] = index; + codeStream.emit(OP_LOADIMMED_FLT); + codeStream.emit(index); break; case TypeReqNone: break; @@ -1078,7 +875,7 @@ TypeReq ConstantNode::getPreferredType() //------------------------------------------------------------ -U32 AssignExprNode::precompile(TypeReq type) +U32 AssignExprNode::compile(CodeStream &codeStream, U32 ip, TypeReq type) { subType = expr->getPreferredType(); if(subType == TypeReqNone) @@ -1096,65 +893,52 @@ U32 AssignExprNode::precompile(TypeReq type) // OP_SETCURVAR_ARRAY_CREATE // OP_TERMINATE_REWIND_STR // OP_SAVEVAR - + //else // eval expr // OP_SETCURVAR_CREATE // varname // OP_SAVEVAR - const U32 addSize = (type != subType ? 1 : 0); - const U32 retSize = expr->precompile(subType); - -#ifdef DEBUG_AST_NODES - if(retSize > 1000) - Con::printf("Bad expr %s", expr->dbgStmtType().c_str()); -#endif - + precompileIdent(varName); - - return retSize + addSize + (arrayIndex ? arrayIndex->precompile(TypeReqString) + (subType == TypeReqString ? 8 : 6 ) : 3); -} - -U32 AssignExprNode::compile(U32 *codeStream, U32 ip, TypeReq type) -{ + ip = expr->compile(codeStream, ip, subType); if(arrayIndex) { if(subType == TypeReqString) - codeStream[ip++] = OP_ADVANCE_STR; + codeStream.emit(OP_ADVANCE_STR); - codeStream[ip++] = OP_LOADIMMED_IDENT; - codeStream[ip] = STEtoU32(varName, ip); - ip++; - codeStream[ip++] = OP_ADVANCE_STR; + codeStream.emit(OP_LOADIMMED_IDENT); + codeStream.emitSTE(varName); + + codeStream.emit(OP_ADVANCE_STR); ip = arrayIndex->compile(codeStream, ip, TypeReqString); - codeStream[ip++] = OP_REWIND_STR; - codeStream[ip++] = OP_SETCURVAR_ARRAY_CREATE; + codeStream.emit(OP_REWIND_STR); + codeStream.emit(OP_SETCURVAR_ARRAY_CREATE); if(subType == TypeReqString) - codeStream[ip++] = OP_TERMINATE_REWIND_STR; + codeStream.emit(OP_TERMINATE_REWIND_STR); } else { - codeStream[ip++] = OP_SETCURVAR_CREATE; - codeStream[ip] = STEtoU32(varName, ip); - ip++; + codeStream.emit(OP_SETCURVAR_CREATE); + codeStream.emitSTE(varName); } switch(subType) { case TypeReqString: - codeStream[ip++] = OP_SAVEVAR_STR; + codeStream.emit(OP_SAVEVAR_STR); break; case TypeReqUInt: - codeStream[ip++] = OP_SAVEVAR_UINT; + codeStream.emit(OP_SAVEVAR_UINT); break; case TypeReqFloat: - codeStream[ip++] = OP_SAVEVAR_FLT; + codeStream.emit(OP_SAVEVAR_FLT); break; case TypeReqNone: break; } if(type != subType) - codeStream[ip++] = conversionOp(subType, type); + codeStream.emit(conversionOp(subType, type)); return ip; } @@ -1212,67 +996,54 @@ static void getAssignOpTypeOp(S32 op, TypeReq &type, U32 &operand) } } -U32 AssignOpExprNode::precompile(TypeReq type) +U32 AssignOpExprNode::compile(CodeStream &codeStream, U32 ip, TypeReq type) { + // goes like this... // eval expr as float or int // if there's an arrayIndex - + // OP_LOADIMMED_IDENT // varName // OP_ADVANCE_STR // eval arrayIndex stringwise // OP_REWIND_STR // OP_SETCURVAR_ARRAY_CREATE - + // else // OP_SETCURVAR_CREATE // varName - + // OP_LOADVAR_FLT or UINT // operand // OP_SAVEVAR_FLT or UINT - + // conversion OP if necessary. getAssignOpTypeOp(op, subType, operand); precompileIdent(varName); - U32 size = expr->precompile(subType); - if(type != subType) - size++; - if(!arrayIndex) - return size + 5; - else - { - size += arrayIndex->precompile(TypeReqString); - return size + 8; - } -} - -U32 AssignOpExprNode::compile(U32 *codeStream, U32 ip, TypeReq type) -{ + ip = expr->compile(codeStream, ip, subType); if(!arrayIndex) { - codeStream[ip++] = OP_SETCURVAR_CREATE; - codeStream[ip] = STEtoU32(varName, ip); - ip++; + codeStream.emit(OP_SETCURVAR_CREATE); + codeStream.emitSTE(varName); } else { - codeStream[ip++] = OP_LOADIMMED_IDENT; - codeStream[ip] = STEtoU32(varName, ip); - ip++; - codeStream[ip++] = OP_ADVANCE_STR; + codeStream.emit(OP_LOADIMMED_IDENT); + codeStream.emitSTE(varName); + + codeStream.emit(OP_ADVANCE_STR); ip = arrayIndex->compile(codeStream, ip, TypeReqString); - codeStream[ip++] = OP_REWIND_STR; - codeStream[ip++] = OP_SETCURVAR_ARRAY_CREATE; + codeStream.emit(OP_REWIND_STR); + codeStream.emit(OP_SETCURVAR_ARRAY_CREATE); } - codeStream[ip++] = (subType == TypeReqFloat) ? OP_LOADVAR_FLT : OP_LOADVAR_UINT; - codeStream[ip++] = operand; - codeStream[ip++] = (subType == TypeReqFloat) ? OP_SAVEVAR_FLT : OP_SAVEVAR_UINT; + codeStream.emit((subType == TypeReqFloat) ? OP_LOADVAR_FLT : OP_LOADVAR_UINT); + codeStream.emit(operand); + codeStream.emit((subType == TypeReqFloat) ? OP_SAVEVAR_FLT : OP_SAVEVAR_UINT); if(subType != type) - codeStream[ip++] = conversionOp(subType, type); - return ip; + codeStream.emit(conversionOp(subType, type)); + return codeStream.tell(); } TypeReq AssignOpExprNode::getPreferredType() @@ -1283,25 +1054,14 @@ TypeReq AssignOpExprNode::getPreferredType() //------------------------------------------------------------ -U32 TTagSetStmtNode::precompileStmt(U32 loopCount) -{ - TORQUE_UNUSED(loopCount); - return 0; -} - -U32 TTagSetStmtNode::compileStmt(U32*, U32 ip, U32, U32) +U32 TTagSetStmtNode::compileStmt(CodeStream&, U32 ip) { return ip; } //------------------------------------------------------------ -U32 TTagDerefNode::precompile(TypeReq) -{ - return 0; -} - -U32 TTagDerefNode::compile(U32*, U32 ip, TypeReq) +U32 TTagDerefNode::compile(CodeStream&, U32 ip, TypeReq) { return ip; } @@ -1313,12 +1073,7 @@ TypeReq TTagDerefNode::getPreferredType() //------------------------------------------------------------ -U32 TTagExprNode::precompile(TypeReq) -{ - return 0; -} - -U32 TTagExprNode::compile(U32*, U32 ip, TypeReq) +U32 TTagExprNode::compile(CodeStream&, U32 ip, TypeReq) { return ip; } @@ -1330,48 +1085,38 @@ TypeReq TTagExprNode::getPreferredType() //------------------------------------------------------------ -U32 FuncCallExprNode::precompile(TypeReq type) +U32 FuncCallExprNode::compile(CodeStream &codeStream, U32 ip, TypeReq type) { // OP_PUSH_FRAME // arg OP_PUSH arg OP_PUSH arg OP_PUSH // eval all the args, then call the function. - + // OP_CALLFUNC // function // namespace // isDot - - U32 size = 0; - if(type != TypeReqString) - size++; + precompileIdent(funcName); precompileIdent(nameSpace); - for(ExprNode *walk = args; walk; walk = (ExprNode *) walk->getNext()) - size += walk->precompile(TypeReqString) + 1; - return size + 5; -} - -U32 FuncCallExprNode::compile(U32 *codeStream, U32 ip, TypeReq type) -{ - codeStream[ip++] = OP_PUSH_FRAME; + + codeStream.emit(OP_PUSH_FRAME); for(ExprNode *walk = args; walk; walk = (ExprNode *) walk->getNext()) { ip = walk->compile(codeStream, ip, TypeReqString); - codeStream[ip++] = OP_PUSH; + codeStream.emit(OP_PUSH); } if(callType == MethodCall || callType == ParentCall) - codeStream[ip++] = OP_CALLFUNC; + codeStream.emit(OP_CALLFUNC); else - codeStream[ip++] = OP_CALLFUNC_RESOLVE; + codeStream.emit(OP_CALLFUNC_RESOLVE); - codeStream[ip] = STEtoU32(funcName, ip); - ip++; - codeStream[ip] = STEtoU32(nameSpace, ip); - ip++; - codeStream[ip++] = callType; + codeStream.emitSTE(funcName); + codeStream.emitSTE(nameSpace); + + codeStream.emit(callType); if(type != TypeReqString) - codeStream[ip++] = conversionOp(TypeReqString, type); - return ip; + codeStream.emit(conversionOp(TypeReqString, type)); + return codeStream.tell(); } TypeReq FuncCallExprNode::getPreferredType() @@ -1382,33 +1127,19 @@ TypeReq FuncCallExprNode::getPreferredType() //------------------------------------------------------------ -U32 AssertCallExprNode::precompile( TypeReq type ) +U32 AssertCallExprNode::compile( CodeStream &codeStream, U32 ip, TypeReq type ) { #ifdef TORQUE_ENABLE_SCRIPTASSERTS - + messageIndex = getCurrentStringTable()->add( message, true, false ); - - U32 exprSize = testExpr->precompile(TypeReqUInt); - return exprSize + 2; - - #else - - return 0; - - #endif -} - -U32 AssertCallExprNode::compile( U32 *codeStream, U32 ip, TypeReq type ) -{ - #ifdef TORQUE_ENABLE_SCRIPTASSERTS - + ip = testExpr->compile( codeStream, ip, TypeReqUInt ); - codeStream[ip++] = OP_ASSERT; - codeStream[ip++] = messageIndex; + codeStream.emit(OP_ASSERT); + codeStream.emit(messageIndex); #endif - return ip; + return codeStream.tell(); } TypeReq AssertCallExprNode::getPreferredType() @@ -1418,12 +1149,13 @@ TypeReq AssertCallExprNode::getPreferredType() //------------------------------------------------------------ -U32 SlotAccessNode::precompile(TypeReq type) +U32 SlotAccessNode::compile(CodeStream &codeStream, U32 ip, TypeReq type) { if(type == TypeReqNone) - return 0; - U32 size = 0; + return ip; + precompileIdent(slotName); + if(arrayExpr) { // eval array @@ -1432,54 +1164,38 @@ U32 SlotAccessNode::precompile(TypeReq type) // OP_TERMINATE_REWIND_STR // OP_SETCURFIELDARRAY // total add of 4 + array precomp - size += 3 + arrayExpr->precompile(TypeReqString); - } - // eval object expression sub + 3 (op_setCurField + OP_SETCUROBJECT) - size += objectExpr->precompile(TypeReqString) + 3; - - // get field in desired type: - return size + 1; -} - -U32 SlotAccessNode::compile(U32 *codeStream, U32 ip, TypeReq type) -{ - if(type == TypeReqNone) - return ip; - - if(arrayExpr) - { + ip = arrayExpr->compile(codeStream, ip, TypeReqString); - codeStream[ip++] = OP_ADVANCE_STR; + codeStream.emit(OP_ADVANCE_STR); } ip = objectExpr->compile(codeStream, ip, TypeReqString); - codeStream[ip++] = OP_SETCUROBJECT; + codeStream.emit(OP_SETCUROBJECT); - codeStream[ip++] = OP_SETCURFIELD; + codeStream.emit(OP_SETCURFIELD); - codeStream[ip] = STEtoU32(slotName, ip); - ip++; + codeStream.emitSTE(slotName); if(arrayExpr) { - codeStream[ip++] = OP_TERMINATE_REWIND_STR; - codeStream[ip++] = OP_SETCURFIELD_ARRAY; + codeStream.emit(OP_TERMINATE_REWIND_STR); + codeStream.emit(OP_SETCURFIELD_ARRAY); } switch(type) { case TypeReqUInt: - codeStream[ip++] = OP_LOADFIELD_UINT; + codeStream.emit(OP_LOADFIELD_UINT); break; case TypeReqFloat: - codeStream[ip++] = OP_LOADFIELD_FLT; + codeStream.emit(OP_LOADFIELD_FLT); break; case TypeReqString: - codeStream[ip++] = OP_LOADFIELD_STR; + codeStream.emit(OP_LOADFIELD_STR); break; case TypeReqNone: break; } - return ip; + return codeStream.tell(); } TypeReq SlotAccessNode::getPreferredType() @@ -1489,38 +1205,21 @@ TypeReq SlotAccessNode::getPreferredType() //----------------------------------------------------------------------------- -U32 InternalSlotAccessNode::precompile(TypeReq type) -{ - if(type == TypeReqNone) - return 0; - - U32 size = 3; - - // eval object expression sub + 3 (op_setCurField + OP_SETCUROBJECT) - size += objectExpr->precompile(TypeReqString); - size += slotExpr->precompile(TypeReqString); - if(type != TypeReqUInt) - size++; - - // get field in desired type: - return size; -} - -U32 InternalSlotAccessNode::compile(U32 *codeStream, U32 ip, TypeReq type) +U32 InternalSlotAccessNode::compile(CodeStream &codeStream, U32 ip, TypeReq type) { if(type == TypeReqNone) return ip; ip = objectExpr->compile(codeStream, ip, TypeReqString); - codeStream[ip++] = OP_SETCUROBJECT; + codeStream.emit(OP_SETCUROBJECT); ip = slotExpr->compile(codeStream, ip, TypeReqString); - codeStream[ip++] = OP_SETCUROBJECT_INTERNAL; - codeStream[ip++] = recurse; + codeStream.emit(OP_SETCUROBJECT_INTERNAL); + codeStream.emit(recurse); if(type != TypeReqUInt) - codeStream[ip++] = conversionOp(TypeReqUInt, type); - return ip; + codeStream.emit(conversionOp(TypeReqUInt, type)); + return codeStream.tell(); } TypeReq InternalSlotAccessNode::getPreferredType() @@ -1530,27 +1229,25 @@ TypeReq InternalSlotAccessNode::getPreferredType() //----------------------------------------------------------------------------- -//------------------------------------------------------------ - -U32 SlotAssignNode::precompile(TypeReq type) +U32 SlotAssignNode::compile(CodeStream &codeStream, U32 ip, TypeReq type) { // first eval the expression TypeReqString - + // if it's an array: - + // if OP_ADVANCE_STR 1 // eval array - + // OP_ADVANCE_STR 1 // evaluate object expr // OP_SETCUROBJECT 1 // OP_SETCURFIELD 1 // fieldName 1 // OP_TERMINATE_REWIND_STR 1 - + // OP_SETCURFIELDARRAY 1 // OP_TERMINATE_REWIND_STR 1 - + // else // OP_ADVANCE_STR // evaluate object expr @@ -1558,69 +1255,47 @@ U32 SlotAssignNode::precompile(TypeReq type) // OP_SETCURFIELD // fieldName // OP_TERMINATE_REWIND_STR - + // OP_SAVEFIELD // convert to return type if necessary. - - U32 size = 0; - if(type != TypeReqString) - size++; - + precompileIdent(slotName); - - size += valueExpr->precompile(TypeReqString); - - if(objectExpr) - size += objectExpr->precompile(TypeReqString) + 5; - else - size += 5; - - if(arrayExpr) - size += arrayExpr->precompile(TypeReqString) + 3; - - if(typeID != -1) - size += 2; - - return size + 1; -} - -U32 SlotAssignNode::compile(U32 *codeStream, U32 ip, TypeReq type) -{ + ip = valueExpr->compile(codeStream, ip, TypeReqString); - codeStream[ip++] = OP_ADVANCE_STR; + codeStream.emit(OP_ADVANCE_STR); if(arrayExpr) { ip = arrayExpr->compile(codeStream, ip, TypeReqString); - codeStream[ip++] = OP_ADVANCE_STR; + codeStream.emit(OP_ADVANCE_STR); } if(objectExpr) { ip = objectExpr->compile(codeStream, ip, TypeReqString); - codeStream[ip++] = OP_SETCUROBJECT; + codeStream.emit(OP_SETCUROBJECT); } else - codeStream[ip++] = OP_SETCUROBJECT_NEW; - codeStream[ip++] = OP_SETCURFIELD; - codeStream[ip] = STEtoU32(slotName, ip); - ip++; + codeStream.emit(OP_SETCUROBJECT_NEW); + codeStream.emit(OP_SETCURFIELD); + codeStream.emitSTE(slotName); + if(arrayExpr) { - codeStream[ip++] = OP_TERMINATE_REWIND_STR; - codeStream[ip++] = OP_SETCURFIELD_ARRAY; + codeStream.emit(OP_TERMINATE_REWIND_STR); + codeStream.emit(OP_SETCURFIELD_ARRAY); } - codeStream[ip++] = OP_TERMINATE_REWIND_STR; - codeStream[ip++] = OP_SAVEFIELD_STR; + codeStream.emit(OP_TERMINATE_REWIND_STR); + codeStream.emit(OP_SAVEFIELD_STR); if(typeID != -1) { - codeStream[ip++] = OP_SETCURFIELD_TYPE; - codeStream[ip++] = typeID; + codeStream.emit(OP_SETCURFIELD_TYPE); + codeStream.emit(typeID); } if(type != TypeReqString) - codeStream[ip++] = conversionOp(TypeReqString, type); - return ip; + codeStream.emit(conversionOp(TypeReqString, type)); + return codeStream.tell(); } TypeReq SlotAssignNode::getPreferredType() @@ -1630,10 +1305,10 @@ TypeReq SlotAssignNode::getPreferredType() //------------------------------------------------------------ -U32 SlotAssignOpNode::precompile(TypeReq type) +U32 SlotAssignOpNode::compile(CodeStream &codeStream, U32 ip, TypeReq type) { // first eval the expression as its type - + // if it's an array: // eval array // OP_ADVANCE_STR @@ -1643,53 +1318,43 @@ U32 SlotAssignOpNode::precompile(TypeReq type) // fieldName // OP_TERMINATE_REWIND_STR // OP_SETCURFIELDARRAY - + // else // evaluate object expr // OP_SETCUROBJECT // OP_SETCURFIELD // fieldName - + // OP_LOADFIELD of appropriate type // operand // OP_SAVEFIELD of appropriate type // convert to return type if necessary. - + getAssignOpTypeOp(op, subType, operand); precompileIdent(slotName); - U32 size = valueExpr->precompile(subType); - if(type != subType) - size++; - if(arrayExpr) - return size + 9 + arrayExpr->precompile(TypeReqString) + objectExpr->precompile(TypeReqString); - else - return size + 6 + objectExpr->precompile(TypeReqString); -} - -U32 SlotAssignOpNode::compile(U32 *codeStream, U32 ip, TypeReq type) -{ + ip = valueExpr->compile(codeStream, ip, subType); if(arrayExpr) { ip = arrayExpr->compile(codeStream, ip, TypeReqString); - codeStream[ip++] = OP_ADVANCE_STR; + codeStream.emit(OP_ADVANCE_STR); } ip = objectExpr->compile(codeStream, ip, TypeReqString); - codeStream[ip++] = OP_SETCUROBJECT; - codeStream[ip++] = OP_SETCURFIELD; - codeStream[ip] = STEtoU32(slotName, ip); - ip++; + codeStream.emit(OP_SETCUROBJECT); + codeStream.emit(OP_SETCURFIELD); + codeStream.emitSTE(slotName); + if(arrayExpr) { - codeStream[ip++] = OP_TERMINATE_REWIND_STR; - codeStream[ip++] = OP_SETCURFIELD_ARRAY; + codeStream.emit(OP_TERMINATE_REWIND_STR); + codeStream.emit(OP_SETCURFIELD_ARRAY); } - codeStream[ip++] = (subType == TypeReqFloat) ? OP_LOADFIELD_FLT : OP_LOADFIELD_UINT; - codeStream[ip++] = operand; - codeStream[ip++] = (subType == TypeReqFloat) ? OP_SAVEFIELD_FLT : OP_SAVEFIELD_UINT; + codeStream.emit((subType == TypeReqFloat) ? OP_LOADFIELD_FLT : OP_LOADFIELD_UINT); + codeStream.emit(operand); + codeStream.emit((subType == TypeReqFloat) ? OP_SAVEFIELD_FLT : OP_SAVEFIELD_UINT); if(subType != type) - codeStream[ip++] = conversionOp(subType, type); - return ip; + codeStream.emit(conversionOp(subType, type)); + return codeStream.tell(); } TypeReq SlotAssignOpNode::getPreferredType() @@ -1700,10 +1365,10 @@ TypeReq SlotAssignOpNode::getPreferredType() //------------------------------------------------------------ -U32 ObjectDeclNode::precompileSubObject(bool) +U32 ObjectDeclNode::compileSubObject(CodeStream &codeStream, U32 ip, bool root) { // goes - + // OP_PUSHFRAME 1 // name expr // OP_PUSH 1 @@ -1715,98 +1380,69 @@ U32 ObjectDeclNode::precompileSubObject(bool) // isSingleton 1 // lineNumber 1 // fail point 1 - + // for each field, eval // OP_ADD_OBJECT (to UINT[0]) 1 // root? 1 - + // add all the sub objects. // OP_END_OBJECT 1 // root? 1 // To fix the stack issue [7/9/2007 Black] // OP_FINISH_OBJECT <-- fail point jumps to this opcode + + codeStream.emit(OP_PUSH_FRAME); + ip = classNameExpr->compile(codeStream, ip, TypeReqString); + codeStream.emit(OP_PUSH); - U32 argSize = 0; - precompileIdent(parentObject); + ip = objectNameExpr->compile(codeStream, ip, TypeReqString); + codeStream.emit(OP_PUSH); for(ExprNode *exprWalk = argList; exprWalk; exprWalk = (ExprNode *) exprWalk->getNext()) - argSize += exprWalk->precompile(TypeReqString) + 1; - argSize += classNameExpr->precompile(TypeReqString) + 1; + { + ip = exprWalk->compile(codeStream, ip, TypeReqString); + codeStream.emit(OP_PUSH); + } + codeStream.emit(OP_CREATE_OBJECT); + codeStream.emitSTE(parentObject); - U32 nameSize = objectNameExpr->precompile(TypeReqString) + 1; - - U32 slotSize = 0; + codeStream.emit(isDatablock); + codeStream.emit(isClassNameInternal); + codeStream.emit(isSingleton); + codeStream.emit(dbgLineNumber); + const U32 failIp = codeStream.emit(0); for(SlotAssignNode *slotWalk = slotDecls; slotWalk; slotWalk = (SlotAssignNode *) slotWalk->getNext()) - slotSize += slotWalk->precompile(TypeReqNone); - - // OP_ADD_OBJECT - U32 subObjSize = 0; + ip = slotWalk->compile(codeStream, ip, TypeReqNone); + codeStream.emit(OP_ADD_OBJECT); + codeStream.emit(root); for(ObjectDeclNode *objectWalk = subObjects; objectWalk; objectWalk = (ObjectDeclNode *) objectWalk->getNext()) - subObjSize += objectWalk->precompileSubObject(false); - - failOffset = 12 + nameSize + argSize + slotSize + subObjSize; - // +1 because the failOffset should jump to OP_FINISH_OBJECT [7/9/2007 Black] - return failOffset + 1; + ip = objectWalk->compileSubObject(codeStream, ip, false); + codeStream.emit(OP_END_OBJECT); + codeStream.emit(root || isDatablock); + // Added to fix the object creation issue [7/9/2007 Black] + failOffset = codeStream.emit(OP_FINISH_OBJECT); + + codeStream.patch(failIp, failOffset); + + return codeStream.tell(); } -U32 ObjectDeclNode::precompile(TypeReq type) +U32 ObjectDeclNode::compile(CodeStream &codeStream, U32 ip, TypeReq type) { // root object decl does: - + // push 0 onto the UINT stack OP_LOADIMMED_UINT // precompiles the subObject(true) // UINT stack now has object id // type conv to type - - U32 ret = 2 + precompileSubObject(true); - if(type != TypeReqUInt) - return ret + 1; - return ret; -} - -U32 ObjectDeclNode::compileSubObject(U32 *codeStream, U32 ip, bool root) -{ - U32 start = ip; - codeStream[ip++] = OP_PUSH_FRAME; - ip = classNameExpr->compile(codeStream, ip, TypeReqString); - codeStream[ip++] = OP_PUSH; - - ip = objectNameExpr->compile(codeStream, ip, TypeReqString); - codeStream[ip++] = OP_PUSH; - for(ExprNode *exprWalk = argList; exprWalk; exprWalk = (ExprNode *) exprWalk->getNext()) - { - ip = exprWalk->compile(codeStream, ip, TypeReqString); - codeStream[ip++] = OP_PUSH; - } - codeStream[ip++] = OP_CREATE_OBJECT; - codeStream[ip] = STEtoU32(parentObject, ip); - ip++; - codeStream[ip++] = isDatablock; - codeStream[ip++] = isClassNameInternal; - codeStream[ip++] = isSingleton; - codeStream[ip++] = dbgLineNumber; - codeStream[ip++] = start + failOffset; - for(SlotAssignNode *slotWalk = slotDecls; slotWalk; slotWalk = (SlotAssignNode *) slotWalk->getNext()) - ip = slotWalk->compile(codeStream, ip, TypeReqNone); - codeStream[ip++] = OP_ADD_OBJECT; - codeStream[ip++] = root; - for(ObjectDeclNode *objectWalk = subObjects; objectWalk; objectWalk = (ObjectDeclNode *) objectWalk->getNext()) - ip = objectWalk->compileSubObject(codeStream, ip, false); - codeStream[ip++] = OP_END_OBJECT; - codeStream[ip++] = root || isDatablock; - // Added to fix the object creation issue [7/9/2007 Black] - codeStream[ip++] = OP_FINISH_OBJECT; - return ip; -} - -U32 ObjectDeclNode::compile(U32 *codeStream, U32 ip, TypeReq type) -{ - codeStream[ip++] = OP_LOADIMMED_UINT; - codeStream[ip++] = 0; + + codeStream.emit(OP_LOADIMMED_UINT); + codeStream.emit(0); ip = compileSubObject(codeStream, ip, true); if(type != TypeReqUInt) - codeStream[ip++] = conversionOp(TypeReqUInt, type); - return ip; -} + codeStream.emit(conversionOp(TypeReqUInt, type)); + return codeStream.tell(); +} + TypeReq ObjectDeclNode::getPreferredType() { return TypeReqUInt; @@ -1814,7 +1450,7 @@ TypeReq ObjectDeclNode::getPreferredType() //------------------------------------------------------------ -U32 FunctionDeclStmtNode::precompileStmt(U32) +U32 FunctionDeclStmtNode::compileStmt(CodeStream &codeStream, U32 ip) { // OP_FUNC_DECL // func name @@ -1828,10 +1464,13 @@ U32 FunctionDeclStmtNode::precompileStmt(U32) // OP_RETURN_VOID setCurrentStringTable(&getFunctionStringTable()); setCurrentFloatTable(&getFunctionFloatTable()); - + argc = 0; for(VarNode *walk = args; walk; walk = (VarNode *)((StmtNode*)walk)->getNext()) + { + precompileIdent(walk->varName); argc++; + } CodeBlock::smInFunction = true; @@ -1839,44 +1478,36 @@ U32 FunctionDeclStmtNode::precompileStmt(U32) precompileIdent(nameSpace); precompileIdent(package); - U32 subSize = precompileBlock(stmts, 0); CodeBlock::smInFunction = false; - - addBreakCount(); - - setCurrentStringTable(&getGlobalStringTable()); - setCurrentFloatTable(&getGlobalFloatTable()); - - endOffset = argc + subSize + 8; - return endOffset; -} - -U32 FunctionDeclStmtNode::compileStmt(U32 *codeStream, U32 ip, U32, U32) -{ + + U32 start = ip; - codeStream[ip++] = OP_FUNC_DECL; - codeStream[ip] = STEtoU32(fnName, ip); - ip++; - codeStream[ip] = STEtoU32(nameSpace, ip); - ip++; - codeStream[ip] = STEtoU32(package, ip); - ip++; - codeStream[ip++] = U32( bool(stmts != NULL) ? 1 : 0 ) + U32( dbgLineNumber << 1 ); - codeStream[ip++] = start + endOffset; - codeStream[ip++] = argc; + codeStream.emit(OP_FUNC_DECL); + codeStream.emitSTE(fnName); + codeStream.emitSTE(nameSpace); + codeStream.emitSTE(package); + + codeStream.emit(U32( bool(stmts != NULL) ? 1 : 0 ) + U32( dbgLineNumber << 1 )); + const U32 endIp = codeStream.emit(0); + codeStream.emit(argc); for(VarNode *walk = args; walk; walk = (VarNode *)((StmtNode*)walk)->getNext()) { - codeStream[ip] = STEtoU32(walk->varName, ip); - ip++; + codeStream.emitSTE(walk->varName); } CodeBlock::smInFunction = true; - ip = compileBlock(stmts, codeStream, ip, 0, 0); + ip = compileBlock(stmts, codeStream, ip); // Add break so breakpoint can be set at closing brace or // in empty function. - addBreakLine( ip ); + addBreakLine(codeStream); CodeBlock::smInFunction = false; - codeStream[ip++] = OP_RETURN_VOID; + codeStream.emit(OP_RETURN_VOID); + + codeStream.patch(endIp, codeStream.tell()); + + setCurrentStringTable(&getGlobalStringTable()); + setCurrentFloatTable(&getGlobalFloatTable()); + return ip; } diff --git a/Engine/source/console/codeBlock.cpp b/Engine/source/console/codeBlock.cpp index c6efd9cf2..1341dc2bd 100644 --- a/Engine/source/console/codeBlock.cpp +++ b/Engine/source/console/codeBlock.cpp @@ -33,7 +33,6 @@ using namespace Compiler; bool CodeBlock::smInFunction = false; -U32 CodeBlock::smBreakLineCount = 0; CodeBlock * CodeBlock::smCodeBlockList = NULL; CodeBlock * CodeBlock::smCurrentCodeBlock = NULL; ConsoleParser *CodeBlock::smCurrentParser = NULL; @@ -456,6 +455,8 @@ bool CodeBlock::read(StringTableEntry fileName, Stream &st) bool CodeBlock::compile(const char *codeFileName, StringTableEntry fileName, const char *inScript, bool overrideNoDso) { + AssertFatal(Con::isMainThread(), "Compiling code on a secondary thread"); + // This will return true, but return value is ignored char *script; chompUTF8BOM( inScript, &script ); @@ -464,7 +465,7 @@ bool CodeBlock::compile(const char *codeFileName, StringTableEntry fileName, con consoleAllocReset(); - STEtoU32 = compileSTEtoU32; + STEtoCode = compileSTEtoCode; gStatementList = NULL; @@ -497,17 +498,23 @@ bool CodeBlock::compile(const char *codeFileName, StringTableEntry fileName, con resetTables(); smInFunction = false; - smBreakLineCount = 0; - setBreakCodeBlock(this); + CodeStream codeStream; + U32 lastIp; if(gStatementList) - codeSize = precompileBlock(gStatementList, 0) + 1; + { + lastIp = compileBlock(gStatementList, codeStream, 0) + 1; + } else + { codeSize = 1; - - lineBreakPairCount = smBreakLineCount; - code = new U32[codeSize + smBreakLineCount * 2]; - lineBreakPairs = code + codeSize; + lastIp = 0; + } + + codeStream.emit(OP_RETURN); + codeStream.emitCodeStream(&codeSize, &code, &lineBreakPairs); + + lineBreakPairCount = codeStream.getNumLineBreaks(); // Write string table data... getGlobalStringTable().write(st); @@ -517,18 +524,10 @@ bool CodeBlock::compile(const char *codeFileName, StringTableEntry fileName, con getGlobalFloatTable().write(st); getFunctionFloatTable().write(st); - smBreakLineCount = 0; - U32 lastIp; - if(gStatementList) - lastIp = compileBlock(gStatementList, code, 0, 0, 0); - else - lastIp = 0; - - if(lastIp != codeSize - 1) + if(lastIp != codeSize) Con::errorf(ConsoleLogEntry::General, "CodeBlock::compile - precompile size mismatch, a precompile/compile function pair is probably mismatched."); - - code[lastIp++] = OP_RETURN; - U32 totSize = codeSize + smBreakLineCount * 2; + + U32 totSize = codeSize + codeStream.getNumLineBreaks() * 2; st.write(codeSize); st.write(lineBreakPairCount); @@ -561,11 +560,13 @@ bool CodeBlock::compile(const char *codeFileName, StringTableEntry fileName, con const char *CodeBlock::compileExec(StringTableEntry fileName, const char *inString, bool noCalls, S32 setFrame) { + AssertFatal(Con::isMainThread(), "Compiling code on a secondary thread"); + // Check for a UTF8 script file char *string; chompUTF8BOM( inString, &string ); - STEtoU32 = evalSTEtoU32; + STEtoCode = evalSTEtoCode; consoleAllocReset(); name = fileName; @@ -617,12 +618,11 @@ const char *CodeBlock::compileExec(StringTableEntry fileName, const char *inStri resetTables(); smInFunction = false; - smBreakLineCount = 0; - setBreakCodeBlock(this); + + CodeStream codeStream; + U32 lastIp = compileBlock(gStatementList, codeStream, 0); - codeSize = precompileBlock(gStatementList, 0) + 1; - - lineBreakPairCount = smBreakLineCount; + lineBreakPairCount = codeStream.getNumLineBreaks(); globalStrings = getGlobalStringTable().build(); globalStringsMaxLen = getGlobalStringTable().totalLen; @@ -632,20 +632,19 @@ const char *CodeBlock::compileExec(StringTableEntry fileName, const char *inStri globalFloats = getGlobalFloatTable().build(); functionFloats = getFunctionFloatTable().build(); - - code = new U32[codeSize + lineBreakPairCount * 2]; - lineBreakPairs = code + codeSize; - - smBreakLineCount = 0; - U32 lastIp = compileBlock(gStatementList, code, 0, 0, 0); - code[lastIp++] = OP_RETURN; + + codeStream.emit(OP_RETURN); + codeStream.emitCodeStream(&codeSize, &code, &lineBreakPairs); + + + dumpInstructions(0, false); consoleAllocReset(); if(lineBreakPairCount && fileName) calcBreakList(); - if(lastIp != codeSize) + if(lastIp+1 != codeSize) Con::warnf(ConsoleLogEntry::General, "precompile size mismatch, precompile: %d compile: %d", codeSize, lastIp); return exec(0, fileName, NULL, 0, 0, noCalls, NULL, setFrame); @@ -674,7 +673,7 @@ String CodeBlock::getFunctionArgs( U32 ip ) U32 fnArgc = code[ ip + 5 ]; for( U32 i = 0; i < fnArgc; ++ i ) { - StringTableEntry var = U32toSTE( code[ ip + i + 6 ] ); + StringTableEntry var = CodeToSTE(code, ip + (i*2) + 6); if( i != 0 ) str.append( ", " ); @@ -696,41 +695,52 @@ String CodeBlock::getFunctionArgs( U32 ip ) void CodeBlock::dumpInstructions( U32 startIp, bool upToReturn ) { U32 ip = startIp; + smInFunction = false; + U32 endFuncIp = 0; + while( ip < codeSize ) { + if (ip > endFuncIp) + { + smInFunction = false; + } + switch( code[ ip ++ ] ) { + case OP_FUNC_DECL: { - StringTableEntry fnName = U32toSTE(code[ip]); - StringTableEntry fnNamespace = U32toSTE(code[ip+1]); - StringTableEntry fnPackage = U32toSTE(code[ip+2]); - bool hasBody = bool(code[ip+3]); - U32 newIp = code[ ip + 4 ]; - U32 argc = code[ ip + 5 ]; + StringTableEntry fnName = CodeToSTE(code, ip); + StringTableEntry fnNamespace = CodeToSTE(code, ip+2); + StringTableEntry fnPackage = CodeToSTE(code, ip+4); + bool hasBody = bool(code[ip+6]); + U32 newIp = code[ ip + 7 ]; + U32 argc = code[ ip + 8 ]; + endFuncIp = newIp; Con::printf( "%i: OP_FUNC_DECL name=%s nspace=%s package=%s hasbody=%i newip=%i argc=%i", ip - 1, fnName, fnNamespace, fnPackage, hasBody, newIp, argc ); // Skip args. - ip += 6 + argc; + ip += 9 + (argc * 2); + smInFunction = true; break; } case OP_CREATE_OBJECT: { - StringTableEntry objParent = U32toSTE(code[ip ]); - bool isDataBlock = code[ip + 1]; - bool isInternal = code[ip + 2]; - bool isSingleton = code[ip + 3]; - U32 lineNumber = code[ip + 4]; - U32 failJump = code[ip + 5]; + StringTableEntry objParent = CodeToSTE(code, ip); + bool isDataBlock = code[ip + 2]; + bool isInternal = code[ip + 3]; + bool isSingleton = code[ip + 4]; + U32 lineNumber = code[ip + 5]; + U32 failJump = code[ip + 6]; Con::printf( "%i: OP_CREATE_OBJECT objParent=%s isDataBlock=%i isInternal=%i isSingleton=%i lineNumber=%i failJump=%i", ip - 1, objParent, isDataBlock, isInternal, isSingleton, lineNumber, failJump ); - ip += 6; + ip += 7; break; } @@ -957,19 +967,19 @@ void CodeBlock::dumpInstructions( U32 startIp, bool upToReturn ) case OP_SETCURVAR: { - StringTableEntry var = U32toSTE(code[ip]); + StringTableEntry var = CodeToSTE(code, ip); Con::printf( "%i: OP_SETCURVAR var=%s", ip - 1, var ); - ip++; + ip += 2; break; } case OP_SETCURVAR_CREATE: { - StringTableEntry var = U32toSTE(code[ip]); + StringTableEntry var = CodeToSTE(code, ip); Con::printf( "%i: OP_SETCURVAR_CREATE var=%s", ip - 1, var ); - ip++; + ip += 2; break; } @@ -1042,9 +1052,10 @@ void CodeBlock::dumpInstructions( U32 startIp, bool upToReturn ) case OP_SETCURFIELD: { - StringTableEntry curField = U32toSTE(code[ip]); + StringTableEntry curField = CodeToSTE(code, ip); Con::printf( "%i: OP_SETCURFIELD field=%s", ip - 1, curField ); - ++ ip; + ip += 2; + break; } case OP_SETCURFIELD_ARRAY: @@ -1161,7 +1172,7 @@ void CodeBlock::dumpInstructions( U32 startIp, bool upToReturn ) case OP_LOADIMMED_FLT: { - F64 val = functionFloats[ code[ ip ] ]; + F64 val = (smInFunction ? functionFloats : globalFloats)[ code[ ip ] ]; Con::printf( "%i: OP_LOADIMMED_FLT val=%f", ip - 1, val ); ++ ip; break; @@ -1169,7 +1180,7 @@ void CodeBlock::dumpInstructions( U32 startIp, bool upToReturn ) case OP_TAG_TO_STR: { - const char* str = functionStrings + code[ ip ]; + const char* str = (smInFunction ? functionStrings : globalStrings) + code[ ip ]; Con::printf( "%i: OP_TAG_TO_STR str=%s", ip - 1, str ); ++ ip; break; @@ -1177,7 +1188,7 @@ void CodeBlock::dumpInstructions( U32 startIp, bool upToReturn ) case OP_LOADIMMED_STR: { - const char* str = functionStrings + code[ ip ]; + const char* str = (smInFunction ? functionStrings : globalStrings) + code[ ip ]; Con::printf( "%i: OP_LOADIMMED_STR str=%s", ip - 1, str ); ++ ip; break; @@ -1185,7 +1196,7 @@ void CodeBlock::dumpInstructions( U32 startIp, bool upToReturn ) case OP_DOCBLOCK_STR: { - const char* str = functionStrings + code[ ip ]; + const char* str = (smInFunction ? functionStrings : globalStrings) + code[ ip ]; Con::printf( "%i: OP_DOCBLOCK_STR str=%s", ip - 1, str ); ++ ip; break; @@ -1193,37 +1204,37 @@ void CodeBlock::dumpInstructions( U32 startIp, bool upToReturn ) case OP_LOADIMMED_IDENT: { - StringTableEntry str = U32toSTE( code[ ip ] ); + StringTableEntry str = CodeToSTE(code, ip); Con::printf( "%i: OP_LOADIMMED_IDENT str=%s", ip - 1, str ); - ++ ip; + ip += 2; break; } case OP_CALLFUNC_RESOLVE: { - StringTableEntry fnNamespace = U32toSTE(code[ip+1]); - StringTableEntry fnName = U32toSTE(code[ip]); + StringTableEntry fnNamespace = CodeToSTE(code, ip+2); + StringTableEntry fnName = CodeToSTE(code, ip); U32 callType = code[ip+2]; Con::printf( "%i: OP_CALLFUNC_RESOLVE name=%s nspace=%s callType=%s", ip - 1, fnName, fnNamespace, callType == FuncCallExprNode::FunctionCall ? "FunctionCall" : callType == FuncCallExprNode::MethodCall ? "MethodCall" : "ParentCall" ); - ip += 3; + ip += 5; break; } case OP_CALLFUNC: { - StringTableEntry fnNamespace = U32toSTE(code[ip+1]); - StringTableEntry fnName = U32toSTE(code[ip]); - U32 callType = code[ip+2]; + StringTableEntry fnNamespace = CodeToSTE(code, ip+2); + StringTableEntry fnName = CodeToSTE(code, ip); + U32 callType = code[ip+4]; Con::printf( "%i: OP_CALLFUNC name=%s nspace=%s callType=%s", ip - 1, fnName, fnNamespace, callType == FuncCallExprNode::FunctionCall ? "FunctionCall" : callType == FuncCallExprNode::MethodCall ? "MethodCall" : "ParentCall" ); - ip += 3; + ip += 5; break; } @@ -1285,7 +1296,7 @@ void CodeBlock::dumpInstructions( U32 startIp, bool upToReturn ) case OP_ASSERT: { - const char* message = functionStrings + code[ ip ]; + const char* message = (smInFunction ? functionStrings : globalStrings) + code[ ip ]; Con::printf( "%i: OP_ASSERT message=%s", ip - 1, message ); ++ ip; break; @@ -1299,31 +1310,34 @@ void CodeBlock::dumpInstructions( U32 startIp, bool upToReturn ) case OP_ITER_BEGIN: { - StringTableEntry varName = U32toSTE( code[ ip ] ); - U32 failIp = code[ ip + 1 ]; + StringTableEntry varName = CodeToSTE(code, ip); + U32 failIp = code[ ip + 2 ]; - Con::printf( "%i: OP_ITER_BEGIN varName=%s failIp=%i", varName, failIp ); + Con::printf( "%i: OP_ITER_BEGIN varName=%s failIp=%i", ip - 1, varName, failIp ); - ++ ip; + ip += 3; + break; } case OP_ITER_BEGIN_STR: { - StringTableEntry varName = U32toSTE( code[ ip ] ); - U32 failIp = code[ ip + 1 ]; + StringTableEntry varName = CodeToSTE(code, ip); + U32 failIp = code[ ip + 2 ]; - Con::printf( "%i: OP_ITER_BEGIN varName=%s failIp=%i", varName, failIp ); + Con::printf( "%i: OP_ITER_BEGIN varName=%s failIp=%i", ip - 1, varName, failIp ); - ip += 2; + ip += 3; + break; } case OP_ITER: { U32 breakIp = code[ ip ]; - Con::printf( "%i: OP_ITER breakIp=%i", breakIp ); + Con::printf( "%i: OP_ITER breakIp=%i", ip - 1, breakIp ); ++ ip; + break; } case OP_ITER_END: @@ -1337,4 +1351,6 @@ void CodeBlock::dumpInstructions( U32 startIp, bool upToReturn ) break; } } + + smInFunction = false; } diff --git a/Engine/source/console/codeBlock.h b/Engine/source/console/codeBlock.h index bf09e79c7..555d7b624 100644 --- a/Engine/source/console/codeBlock.h +++ b/Engine/source/console/codeBlock.h @@ -38,7 +38,6 @@ private: static CodeBlock* smCurrentCodeBlock; public: - static U32 smBreakLineCount; static bool smInFunction; static Compiler::ConsoleParser * smCurrentParser; diff --git a/Engine/source/console/compiledEval.cpp b/Engine/source/console/compiledEval.cpp index 37f621997..18557e0c9 100644 --- a/Engine/source/console/compiledEval.cpp +++ b/Engine/source/console/compiledEval.cpp @@ -422,8 +422,8 @@ const char *CodeBlock::exec(U32 ip, const char *functionName, Namespace *thisNam if(argv) { // assume this points into a function decl: - U32 fnArgc = code[ip + 5]; - thisFunctionName = U32toSTE(code[ip]); + U32 fnArgc = code[ip + 2 + 6]; + thisFunctionName = CodeToSTE(code, ip); argc = getMin(argc-1, fnArgc); // argv[0] is func name if(gEvalState.traceOn) { @@ -458,11 +458,11 @@ const char *CodeBlock::exec(U32 ip, const char *functionName, Namespace *thisNam popFrame = true; for(i = 0; i < argc; i++) { - StringTableEntry var = U32toSTE(code[ip + i + 6]); + StringTableEntry var = CodeToSTE(code, ip + (2 + 6 + 1) + (i * 2)); gEvalState.setCurVarNameCreate(var); gEvalState.setStringVariable(argv[i+1]); } - ip = ip + fnArgc + 6; + ip = ip + (fnArgc * 2) + (2 + 6 + 1); curFloatTable = functionFloats; curStringTable = functionStrings; curStringTableLen = functionStringsMaxLen; @@ -559,11 +559,11 @@ breakContinue: case OP_FUNC_DECL: if(!noCalls) { - fnName = U32toSTE(code[ip]); - fnNamespace = U32toSTE(code[ip+1]); - fnPackage = U32toSTE(code[ip+2]); - bool hasBody = ( code[ ip + 3 ] & 0x01 ) != 0; - U32 lineNumber = code[ ip + 3 ] >> 1; + fnName = CodeToSTE(code, ip); + fnNamespace = CodeToSTE(code, ip+2); + fnPackage = CodeToSTE(code, ip+4); + bool hasBody = ( code[ ip + 6 ] & 0x01 ) != 0; + U32 lineNumber = code[ ip + 6 ] >> 1; Namespace::unlinkPackages(); ns = Namespace::find(fnNamespace, fnPackage); @@ -586,18 +586,18 @@ breakContinue: //Con::printf("Adding function %s::%s (%d)", fnNamespace, fnName, ip); } - ip = code[ip + 4]; + ip = code[ip + 7]; break; case OP_CREATE_OBJECT: { // Read some useful info. - objParent = U32toSTE(code[ip ]); - bool isDataBlock = code[ip + 1]; - bool isInternal = code[ip + 2]; - bool isSingleton = code[ip + 3]; - U32 lineNumber = code[ip + 4]; - failJump = code[ip + 5]; + objParent = CodeToSTE(code, ip); + bool isDataBlock = code[ip + 2]; + bool isInternal = code[ip + 3]; + bool isSingleton = code[ip + 4]; + U32 lineNumber = code[ip + 5]; + failJump = code[ip + 6]; // If we don't allow calls, we certainly don't allow creating objects! // Moved this to after failJump is set. Engine was crashing when @@ -848,7 +848,7 @@ breakContinue: } // Advance the IP past the create info... - ip += 6; + ip += 7; break; } @@ -1170,8 +1170,8 @@ breakContinue: break; case OP_SETCURVAR: - var = U32toSTE(code[ip]); - ip++; + var = CodeToSTE(code, ip); + ip += 2; // If a variable is set, then these must be NULL. It is necessary // to set this here so that the vector parser can appropriately @@ -1190,8 +1190,8 @@ breakContinue: break; case OP_SETCURVAR_CREATE: - var = U32toSTE(code[ip]); - ip++; + var = CodeToSTE(code, ip); + ip += 2; // See OP_SETCURVAR prevField = NULL; @@ -1310,9 +1310,9 @@ breakContinue: // Save the previous field for parsing vector fields. prevField = curField; dStrcpy( prevFieldArray, curFieldArray ); - curField = U32toSTE(code[ip]); + curField = CodeToSTE(code, ip); curFieldArray[0] = 0; - ip++; + ip += 2; break; case OP_SETCURFIELD_ARRAY: @@ -1504,28 +1504,38 @@ breakContinue: break; case OP_LOADIMMED_IDENT: - STR.setStringValue(U32toSTE(code[ip++])); + STR.setStringValue(CodeToSTE(code, ip)); + ip += 2; break; case OP_CALLFUNC_RESOLVE: // This deals with a function that is potentially living in a namespace. - fnNamespace = U32toSTE(code[ip+1]); - fnName = U32toSTE(code[ip]); + fnNamespace = CodeToSTE(code, ip+2); + fnName = CodeToSTE(code, ip); // Try to look it up. ns = Namespace::find(fnNamespace); nsEntry = ns->lookup(fnName); if(!nsEntry) { - ip+= 3; + ip+= 5; Con::warnf(ConsoleLogEntry::General, "%s: Unable to find function %s%s%s", - getFileLine(ip-4), fnNamespace ? fnNamespace : "", + getFileLine(ip-7), fnNamespace ? fnNamespace : "", fnNamespace ? "::" : "", fnName); STR.popFrame(); break; } + // Now fall through to OP_CALLFUNC... + // Now, rewrite our code a bit (ie, avoid future lookups) and fall + // through to OP_CALLFUNC +#ifdef TORQUE_64 + *((U64*)(code+ip+2)) = ((U64)nsEntry); +#else + code[ip+2] = ((U32)nsEntry); +#endif + code[ip-1] = OP_CALLFUNC; case OP_CALLFUNC: { @@ -1535,7 +1545,7 @@ breakContinue: // or just on the object. S32 routingId = 0; - fnName = U32toSTE(code[ip]); + fnName = CodeToSTE(code, ip); //if this is called from inside a function, append the ip and codeptr if( gEvalState.getStackDepth() > 0 ) @@ -1544,9 +1554,9 @@ breakContinue: gEvalState.getCurrentFrame().ip = ip - 1; } - U32 callType = code[ip+2]; + U32 callType = code[ip+4]; - ip += 3; + ip += 5; STR.getArgcArgv(fnName, &callArgc, &callArgv); const char *componentReturnValue = ""; @@ -1555,9 +1565,12 @@ breakContinue: { if( !nsEntry ) { - // We must not have come from OP_CALLFUNC_RESOLVE, so figure out - // our own entry. - nsEntry = Namespace::global()->lookup( fnName ); +#ifdef TORQUE_64 + nsEntry = ((Namespace::Entry *) *((U64*)(code+ip-3))); +#else + nsEntry = ((Namespace::Entry *) *(code+ip-3)); +#endif + ns = NULL; } ns = NULL; } @@ -1618,7 +1631,7 @@ breakContinue: { if(!noCalls && !( routingId == MethodOnComponent ) ) { - Con::warnf(ConsoleLogEntry::General,"%s: Unknown command %s.", getFileLine(ip-4), fnName); + Con::warnf(ConsoleLogEntry::General,"%s: Unknown command %s.", getFileLine(ip-6), fnName); if(callType == FuncCallExprNode::MethodCall) { Con::warnf(ConsoleLogEntry::General, " Object %s(%d) %s", @@ -1652,16 +1665,16 @@ breakContinue: // which is useful behavior when debugging so I'm ifdefing this out for debug builds. if(nsEntry->mToolOnly && ! Con::isCurrentScriptToolScript()) { - Con::errorf(ConsoleLogEntry::Script, "%s: %s::%s - attempting to call tools only function from outside of tools.", getFileLine(ip-4), nsName, fnName); + Con::errorf(ConsoleLogEntry::Script, "%s: %s::%s - attempting to call tools only function from outside of tools.", getFileLine(ip-6), nsName, fnName); } else #endif if((nsEntry->mMinArgs && S32(callArgc) < nsEntry->mMinArgs) || (nsEntry->mMaxArgs && S32(callArgc) > nsEntry->mMaxArgs)) { Con::warnf(ConsoleLogEntry::Script, "%s: %s::%s - wrong number of arguments (got %i, expected min %i and max %i).", - getFileLine(ip-4), nsName, fnName, + getFileLine(ip-6), nsName, fnName, callArgc, nsEntry->mMinArgs, nsEntry->mMaxArgs); - Con::warnf(ConsoleLogEntry::Script, "%s: usage: %s", getFileLine(ip-4), nsEntry->mUsage); + Con::warnf(ConsoleLogEntry::Script, "%s: usage: %s", getFileLine(ip-6), nsEntry->mUsage); STR.popFrame(); } else @@ -1725,7 +1738,7 @@ breakContinue: case Namespace::Entry::VoidCallbackType: nsEntry->cb.mVoidCallbackFunc(gEvalState.thisObject, callArgc, callArgv); if( code[ ip ] != OP_STR_TO_NONE && Con::getBoolVariable( "$Con::warnVoidAssignment", true ) ) - Con::warnf(ConsoleLogEntry::General, "%s: Call to %s in %s uses result of void function call.", getFileLine(ip-4), fnName, functionName); + Con::warnf(ConsoleLogEntry::General, "%s: Call to %s in %s uses result of void function call.", getFileLine(ip-6), fnName, functionName); STR.popFrame(); STR.setStringValue(""); @@ -1844,8 +1857,8 @@ breakContinue: case OP_ITER_BEGIN: { - StringTableEntry varName = U32toSTE( code[ ip ] ); - U32 failIp = code[ ip + 1 ]; + StringTableEntry varName = CodeToSTE(code, ip); + U32 failIp = code[ ip + 2 ]; IterStackRecord& iter = iterStack[ _ITER ]; @@ -1880,7 +1893,7 @@ breakContinue: STR.push(); - ip += 2; + ip += 3; break; } diff --git a/Engine/source/console/compiler.cpp b/Engine/source/console/compiler.cpp index ba8a0c314..ca1282ca6 100644 --- a/Engine/source/console/compiler.cpp +++ b/Engine/source/console/compiler.cpp @@ -60,29 +60,27 @@ namespace Compiler CompilerFloatTable *gCurrentFloatTable, gGlobalFloatTable, gFunctionFloatTable; DataChunker gConsoleAllocator; CompilerIdentTable gIdentTable; - CodeBlock *gCurBreakBlock; //------------------------------------------------------------ - - CodeBlock *getBreakCodeBlock() { return gCurBreakBlock; } - void setBreakCodeBlock(CodeBlock *cb) { gCurBreakBlock = cb; } - - //------------------------------------------------------------ - - U32 evalSTEtoU32(StringTableEntry ste, U32) + void evalSTEtoCode(StringTableEntry ste, U32 ip, U32 *ptr) { - return *((U32 *) &ste); +#ifdef TORQUE_64 + *((U64*)(ptr) = (U64)ste; +#else + *ptr = (U32)ste; +#endif } - - U32 compileSTEtoU32(StringTableEntry ste, U32 ip) + + void compileSTEtoCode(StringTableEntry ste, U32 ip, U32 *ptr) { if(ste) getIdentTable().add(ste, ip); - return 0; + *ptr = 0; + *(ptr+1) = 0; } - - U32 (*STEtoU32)(StringTableEntry ste, U32 ip) = evalSTEtoU32; + + void (*STEtoCode)(StringTableEntry ste, U32 ip, U32 *ptr) = evalSTEtoCode; //------------------------------------------------------------ @@ -286,3 +284,131 @@ void CompilerIdentTable::write(Stream &st) st.write(el->ip); } } + +//------------------------------------------------------------------------- + +U8 *CodeStream::allocCode(U32 sz) +{ + U8 *ptr = NULL; + if (mCodeHead) + { + const U32 bytesLeft = BlockSize - mCodeHead->size; + if (bytesLeft > sz) + { + ptr = mCodeHead->data + mCodeHead->size; + mCodeHead->size += sz; + return ptr; + } + } + + CodeData *data = new CodeData; + data->data = (U8*)dMalloc(BlockSize); + data->size = sz; + data->next = NULL; + + if (mCodeHead) + mCodeHead->next = data; + mCodeHead = data; + if (mCode == NULL) + mCode = data; + return data->data; +} + +//------------------------------------------------------------------------- + +void CodeStream::fixLoop(U32 loopBlockStart, U32 breakPoint, U32 continuePoint) +{ + AssertFatal(mFixStack.size() > 0, "Fix stack mismatch"); + + U32 fixStart = mFixStack[mFixStack.size()-1]; + for (U32 i=fixStart; inext) + { + U32 bytesToCopy = itr->size > outBytes ? outBytes : itr->size; + dMemcpy(outPtr, itr->data, bytesToCopy); + outPtr += bytesToCopy; + outBytes -= bytesToCopy; + } + + *lineBreaks = *stream + mCodePos; + dMemcpy(*lineBreaks, mBreakLines.address(), sizeof(U32) * mBreakLines.size()); + + // Apply patches on top + for (U32 i=0; inext : NULL; + while (itr != NULL) + { + CodeData *next = itr->next; + dFree(itr->data); + dFree(itr); + itr = next; + } + + if (mCode) + { + mCode->size = 0; + mCode->next = NULL; + mCodeHead = mCode; + } +} + diff --git a/Engine/source/console/compiler.h b/Engine/source/console/compiler.h index 66e3966b9..c4b4f94af 100644 --- a/Engine/source/console/compiler.h +++ b/Engine/source/console/compiler.h @@ -24,6 +24,12 @@ #ifndef _COMPILER_H_ #define _COMPILER_H_ +//#define DEBUG_CODESTREAM + +#ifdef DEBUG_CODESTREAM +#include +#endif + class Stream; class DataChunker; @@ -49,7 +55,7 @@ namespace Compiler OP_JMPIFF, OP_JMPIF, OP_JMPIFNOT_NP, - OP_JMPIF_NP, + OP_JMPIF_NP, // 10 OP_JMP, OP_RETURN, // fixes a bug when not explicitly returning a value @@ -60,7 +66,7 @@ namespace Compiler OP_CMPLT, OP_CMPLE, OP_CMPNE, - OP_XOR, + OP_XOR, // 20 OP_MOD, OP_BITAND, OP_BITOR, @@ -71,7 +77,7 @@ namespace Compiler OP_SHR, OP_SHL, OP_AND, - OP_OR, + OP_OR, // 30 OP_ADD, OP_SUB, @@ -84,7 +90,7 @@ namespace Compiler OP_SETCURVAR_ARRAY, OP_SETCURVAR_ARRAY_CREATE, - OP_LOADVAR_UINT, + OP_LOADVAR_UINT,// 40 OP_LOADVAR_FLT, OP_LOADVAR_STR, @@ -97,7 +103,7 @@ namespace Compiler OP_SETCUROBJECT_INTERNAL, OP_SETCURFIELD, - OP_SETCURFIELD_ARRAY, + OP_SETCURFIELD_ARRAY, // 50 OP_SETCURFIELD_TYPE, OP_LOADFIELD_UINT, @@ -110,7 +116,7 @@ namespace Compiler OP_STR_TO_UINT, OP_STR_TO_FLT, - OP_STR_TO_NONE, + OP_STR_TO_NONE, // 60 OP_FLT_TO_UINT, OP_FLT_TO_STR, OP_FLT_TO_NONE, @@ -121,7 +127,7 @@ namespace Compiler OP_LOADIMMED_UINT, OP_LOADIMMED_FLT, OP_TAG_TO_STR, - OP_LOADIMMED_STR, + OP_LOADIMMED_STR, // 70 OP_DOCBLOCK_STR, OP_LOADIMMED_IDENT, @@ -133,7 +139,7 @@ namespace Compiler OP_ADVANCE_STR_COMMA, OP_ADVANCE_STR_NUL, OP_REWIND_STR, - OP_TERMINATE_REWIND_STR, + OP_TERMINATE_REWIND_STR, // 80 OP_COMPARE_STR, OP_PUSH, @@ -147,14 +153,14 @@ namespace Compiler OP_ITER, ///< Enter foreach loop. OP_ITER_END, ///< End foreach loop. - OP_INVALID + OP_INVALID // 90 }; //------------------------------------------------------------ F64 consoleStringToNumber(const char *str, StringTableEntry file = 0, U32 line = 0); - U32 precompileBlock(StmtNode *block, U32 loopCount); - U32 compileBlock(StmtNode *block, U32 *codeStream, U32 ip, U32 continuePoint, U32 breakPoint); + + U32 compileBlock(StmtNode *block, CodeStream &codeStream, U32 ip); //------------------------------------------------------------ @@ -218,15 +224,19 @@ namespace Compiler //------------------------------------------------------------ - inline StringTableEntry U32toSTE(U32 u) + inline StringTableEntry CodeToSTE(U32 *code, U32 ip) { - return *((StringTableEntry *) &u); +#ifdef TORQUE_64 + return (StringTableEntry)(*((U64*)(code+ip))); +#else + return (StringTableEntry)(*(code+ip)); +#endif } - extern U32 (*STEtoU32)(StringTableEntry ste, U32 ip); - - U32 evalSTEtoU32(StringTableEntry ste, U32); - U32 compileSTEtoU32(StringTableEntry ste, U32 ip); + extern void (*STEtoCode)(StringTableEntry ste, U32 ip, U32 *ptr); + + void evalSTEtoCode(StringTableEntry ste, U32 ip, U32 *ptr); + void compileSTEtoCode(StringTableEntry ste, U32 ip, U32 *ptr); CompilerStringTable *getCurrentStringTable(); CompilerStringTable &getGlobalStringTable(); @@ -244,9 +254,6 @@ namespace Compiler void precompileIdent(StringTableEntry ident); - CodeBlock *getBreakCodeBlock(); - void setBreakCodeBlock(CodeBlock *cb); - /// Helper function to reset the float, string, and ident tables to a base /// starting state. void resetTables(); @@ -257,4 +264,167 @@ namespace Compiler extern bool gSyntaxError; }; +/// Utility class to emit and patch bytecode +class CodeStream +{ +public: + + enum FixType + { + // For loops + FIXTYPE_LOOPBLOCKSTART, + FIXTYPE_BREAK, + FIXTYPE_CONTINUE + }; + + enum Constants + { + BlockSize = 16384, + }; + +protected: + + typedef struct PatchEntry + { + U32 addr; ///< Address to patch + U32 value; ///< Value to place at addr + + PatchEntry() {;} + PatchEntry(U32 a, U32 v) : addr(a), value(v) {;} + } PatchEntry; + + typedef struct CodeData + { + U8 *data; ///< Allocated data (size is BlockSize) + U32 size; ///< Bytes used in data + CodeData *next; ///< Next block + }; + + /// @name Emitted code + /// { + CodeData *mCode; + CodeData *mCodeHead; + U32 mCodePos; + /// } + + /// @name Code fixing stacks + /// { + Vector mFixList; + Vector mFixStack; + Vector mFixLoopStack; + Vector mPatchList; + /// } + + Vector mBreakLines; ///< Line numbers + +public: + + CodeStream() : mCode(0), mCodeHead(NULL), mCodePos(0) + { + } + + ~CodeStream() + { + reset(); + + if (mCode) + delete mCode; + } + + U8 *allocCode(U32 sz); + + inline U32 emit(U32 code) + { + U32 *ptr = (U32*)allocCode(4); + *ptr = code; +#ifdef DEBUG_CODESTREAM + printf("code[%u] = %u\n", mCodePos, code); +#endif + return mCodePos++; + } + + inline void patch(U32 addr, U32 code) + { +#ifdef DEBUG_CODESTREAM + printf("patch[%u] = %u\n", addr, code); +#endif + mPatchList.push_back(PatchEntry(addr, code)); + } + + inline U32 emitSTE(const char *code) + { + U64 *ptr = (U64*)allocCode(8); + *ptr = 0; + Compiler::STEtoCode(code, mCodePos, (U32*)ptr); +#ifdef DEBUG_CODESTREAM + printf("code[%u] = %s\n", mCodePos, code); +#endif + mCodePos += 2; + return mCodePos-2; + } + + inline U32 tell() + { + return mCodePos; + } + + inline bool inLoop() + { + for (U32 i=0; i 0, "Fix stack mismatch"); + + U32 newSize = mFixStack[mFixStack.size()-1]; + while (mFixList.size() > newSize) + mFixList.pop_back(); + mFixStack.pop_back(); + mFixLoopStack.pop_back(); + } + + void fixLoop(U32 loopBlockStart, U32 breakPoint, U32 continuePoint); + + inline void addBreakLine(U32 lineNumber, U32 ip) + { + mBreakLines.push_back(lineNumber); + mBreakLines.push_back(ip); + } + + inline U32 getNumLineBreaks() + { + return mBreakLines.size() / 2; + } + + void emitCodeStream(U32 *size, U32 **stream, U32 **lineBreaks); + + void reset(); +}; + #endif diff --git a/Engine/source/console/console.h b/Engine/source/console/console.h index 3c5718c48..e5d4cbe23 100644 --- a/Engine/source/console/console.h +++ b/Engine/source/console/console.h @@ -182,7 +182,8 @@ namespace Con /// 09/12/07 - CAF - 43->44 remove newmsg operator /// 09/27/07 - RDB - 44->45 Patch from Andreas Kirsch: Added opcode to support correct void return /// 01/13/09 - TMS - 45->46 Added script assert - DSOVersion = 46, + /// 09/07/14 - jamesu - 47->47 64bit support + DSOVersion = 47, MaxLineLength = 512, ///< Maximum length of a line of console input. MaxDataTypes = 256 ///< Maximum number of registered data types. From 73c51e5d1ae4798c07cf07a9458307b6bb2e9df8 Mon Sep 17 00:00:00 2001 From: James Urquhart Date: Sun, 7 Sep 2014 21:49:05 +0100 Subject: [PATCH 2/6] Fix leak when freeing compiler stream --- Engine/source/console/compiler.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Engine/source/console/compiler.h b/Engine/source/console/compiler.h index c4b4f94af..2eb6da7e6 100644 --- a/Engine/source/console/compiler.h +++ b/Engine/source/console/compiler.h @@ -328,7 +328,10 @@ public: reset(); if (mCode) + { + dFree(mCode->data); delete mCode; + } } U8 *allocCode(U32 sz); From e6ccc26a879c35afb6d0eaf0a5914981fef6837d Mon Sep 17 00:00:00 2001 From: James Urquhart Date: Sun, 7 Sep 2014 22:07:22 +0100 Subject: [PATCH 3/6] Remove debug instruction dump --- Engine/source/console/codeBlock.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Engine/source/console/codeBlock.cpp b/Engine/source/console/codeBlock.cpp index 1341dc2bd..9dec41417 100644 --- a/Engine/source/console/codeBlock.cpp +++ b/Engine/source/console/codeBlock.cpp @@ -636,8 +636,7 @@ const char *CodeBlock::compileExec(StringTableEntry fileName, const char *inStri codeStream.emit(OP_RETURN); codeStream.emitCodeStream(&codeSize, &code, &lineBreakPairs); - - dumpInstructions(0, false); + //dumpInstructions(0, false); consoleAllocReset(); From 06b463399b6ac53a9925bdda6891bf7123b787e7 Mon Sep 17 00:00:00 2001 From: James Urquhart Date: Sun, 7 Sep 2014 22:49:45 +0100 Subject: [PATCH 4/6] Function Call optimization is now optional (Can cause a problem with package lookups) --- Engine/source/console/compiledEval.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Engine/source/console/compiledEval.cpp b/Engine/source/console/compiledEval.cpp index 18557e0c9..7af130847 100644 --- a/Engine/source/console/compiledEval.cpp +++ b/Engine/source/console/compiledEval.cpp @@ -45,6 +45,9 @@ #include "materials/materialManager.h" #endif +// Uncomment to optimize function calls at the expense of potential invalid package lookups +//#define COMPILER_OPTIMIZE_FUNCTION_CALLS + using namespace Compiler; enum EvalConstants { @@ -1527,6 +1530,7 @@ breakContinue: break; } +#ifdef COMPILER_OPTIMIZE_FUNCTION_CALLS // Now fall through to OP_CALLFUNC... // Now, rewrite our code a bit (ie, avoid future lookups) and fall // through to OP_CALLFUNC @@ -1536,6 +1540,7 @@ breakContinue: code[ip+2] = ((U32)nsEntry); #endif code[ip-1] = OP_CALLFUNC; +#endif case OP_CALLFUNC: { @@ -1565,10 +1570,14 @@ breakContinue: { if( !nsEntry ) { +#ifdef COMPILER_OPTIMIZE_FUNCTION_CALLS #ifdef TORQUE_64 nsEntry = ((Namespace::Entry *) *((U64*)(code+ip-3))); #else nsEntry = ((Namespace::Entry *) *(code+ip-3)); +#endif +#else + nsEntry = Namespace::global()->lookup( fnName ); #endif ns = NULL; } From 057f91d373f6def233850005c4cce04bebc8e390 Mon Sep 17 00:00:00 2001 From: James Urquhart Date: Mon, 8 Sep 2014 11:27:01 +0100 Subject: [PATCH 5/6] Add vector include in compiler header for CodeStream --- Engine/source/console/compiler.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Engine/source/console/compiler.h b/Engine/source/console/compiler.h index 2eb6da7e6..a4acad9ba 100644 --- a/Engine/source/console/compiler.h +++ b/Engine/source/console/compiler.h @@ -37,6 +37,9 @@ class DataChunker; #include "console/ast.h" #include "console/codeBlock.h" +#ifndef _TVECTOR_H_ +#include "core/util/tVector.h" +#endif namespace Compiler { From 1e3db968ace56856b541850c68f6a7ebf2275307 Mon Sep 17 00:00:00 2001 From: James Urquhart Date: Sat, 13 Sep 2014 09:02:57 +0100 Subject: [PATCH 6/6] Update console.h Fix typo in version command --- Engine/source/console/console.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Engine/source/console/console.h b/Engine/source/console/console.h index e5d4cbe23..7d6529bde 100644 --- a/Engine/source/console/console.h +++ b/Engine/source/console/console.h @@ -182,7 +182,7 @@ namespace Con /// 09/12/07 - CAF - 43->44 remove newmsg operator /// 09/27/07 - RDB - 44->45 Patch from Andreas Kirsch: Added opcode to support correct void return /// 01/13/09 - TMS - 45->46 Added script assert - /// 09/07/14 - jamesu - 47->47 64bit support + /// 09/07/14 - jamesu - 46->47 64bit support DSOVersion = 47, MaxLineLength = 512, ///< Maximum length of a line of console input.