Merge pull request #13 from eightyeight/x64

jamesu's AST refactor
This commit is contained in:
LuisAntonRebollo 2014-09-26 00:06:01 +02:00
commit c633933554
9 changed files with 973 additions and 1039 deletions

View file

@ -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

File diff suppressed because it is too large Load diff

View file

@ -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,18 @@ 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 +672,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 +694,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 +966,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 +1051,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 +1171,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 +1179,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 +1187,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 +1195,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 +1203,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 +1295,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 +1309,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 +1350,6 @@ void CodeBlock::dumpInstructions( U32 startIp, bool upToReturn )
break;
}
}
smInFunction = false;
}

View file

@ -38,7 +38,6 @@ private:
static CodeBlock* smCurrentCodeBlock;
public:
static U32 smBreakLineCount;
static bool smInFunction;
static Compiler::ConsoleParser * smCurrentParser;

View file

@ -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 {
@ -422,8 +425,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 +461,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 +562,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 +589,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 +851,7 @@ breakContinue:
}
// Advance the IP past the create info...
ip += 6;
ip += 7;
break;
}
@ -1170,8 +1173,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 +1193,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 +1313,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 +1507,40 @@ 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;
}
#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
#ifdef TORQUE_CPU_X64
*((U64*)(code+ip+2)) = ((U64)nsEntry);
#else
code[ip+2] = ((U32)nsEntry);
#endif
code[ip-1] = OP_CALLFUNC;
#endif
case OP_CALLFUNC:
{
@ -1535,7 +1550,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 +1559,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 +1570,16 @@ breakContinue:
{
if( !nsEntry )
{
// We must not have come from OP_CALLFUNC_RESOLVE, so figure out
// our own entry.
#ifdef COMPILER_OPTIMIZE_FUNCTION_CALLS
#ifdef TORQUE_CPU_X64
nsEntry = ((Namespace::Entry *) *((U64*)(code+ip-3)));
#else
nsEntry = ((Namespace::Entry *) *(code+ip-3));
#endif
#else
nsEntry = Namespace::global()->lookup( fnName );
#endif
ns = NULL;
}
ns = NULL;
}
@ -1618,7 +1640,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 +1674,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 +1747,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 +1866,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 +1902,7 @@ breakContinue:
STR.push();
ip += 2;
ip += 3;
break;
}

View file

@ -60,60 +60,27 @@ namespace Compiler
CompilerFloatTable *gCurrentFloatTable, gGlobalFloatTable, gFunctionFloatTable;
DataChunker gConsoleAllocator;
CompilerIdentTable gIdentTable;
CodeBlock *gCurBreakBlock;
//------------------------------------------------------------
CodeBlock *getBreakCodeBlock() { return gCurBreakBlock; }
void setBreakCodeBlock(CodeBlock *cb) { gCurBreakBlock = cb; }
//------------------------------------------------------------
#ifdef TORQUE_CPU_X64
// Fixed unsafe conversion from pointer to U32. @todo x64 revise
U32 u32toSTEId = 0;
typedef Map< U32, StringTableEntry > U32toSteMap;
U32toSteMap u32toSTEMap;
StringTableEntry U32toSTE( U32 u )
{
// @todo x64 Added thread-safe convertion.
const U32toSteMap::Iterator result = u32toSTEMap.find( u );
AssertFatal( result != u32toSTEMap.end( ),
"Don't converted U32 to STE. See evalSTEtoU32()." );
return result->value;
}
U32 evalSTEtoU32( StringTableEntry ste, U32 )
{
// @todo x64 Added thread-safe convertion.
u32toSTEMap.insert( u32toSTEId++, ste );
return (u32toSTEId - 1); // pointer to inserted
}
#else
StringTableEntry U32toSTE(U32 u)
{
return *((StringTableEntry *) &u);
}
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;
//------------------------------------------------------------
@ -317,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; i<mFixList.size(); i += 2)
{
FixType type = (FixType)mFixList[i+1];
U32 fixedIp = 0;
bool valid = true;
switch (type)
{
case FIXTYPE_LOOPBLOCKSTART:
fixedIp = loopBlockStart;
break;
case FIXTYPE_BREAK:
fixedIp = breakPoint;
break;
case FIXTYPE_CONTINUE:
fixedIp = continuePoint;
break;
default:
//Con::warnf("Address %u fixed as %u", mFixList[i], mFixList[i+1]);
valid = false;
break;
}
if (valid)
{
patch(mFixList[i], fixedIp);
}
}
}
//-------------------------------------------------------------------------
void CodeStream::emitCodeStream(U32 *size, U32 **stream, U32 **lineBreaks)
{
// Alloc stream
U32 numLineBreaks = getNumLineBreaks();
*stream = new U32[mCodePos + (numLineBreaks * 2)];
dMemset(*stream, '\0', mCodePos + (numLineBreaks * 2));
*size = mCodePos;
// Dump chunks & line breaks
U32 outBytes = mCodePos * sizeof(U32);
U8 *outPtr = *((U8**)stream);
for (CodeData *itr = mCode; itr != NULL; itr = itr->next)
{
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; i<mPatchList.size(); i++)
{
PatchEntry &e = mPatchList[i];
(*stream)[e.addr] = e.value;
}
}
//-------------------------------------------------------------------------
void CodeStream::reset()
{
mCodePos = 0;
mFixStack.clear();
mFixLoopStack.clear();
mFixList.clear();
mBreakLines.clear();
// Pop down to one code block
CodeData *itr = mCode ? mCode->next : 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;
}
}

View file

@ -24,6 +24,12 @@
#ifndef _COMPILER_H_
#define _COMPILER_H_
//#define DEBUG_CODESTREAM
#ifdef DEBUG_CODESTREAM
#include <stdio.h>
#endif
class Stream;
class DataChunker;
@ -31,6 +37,9 @@ class DataChunker;
#include "console/ast.h"
#include "console/codeBlock.h"
#ifndef _TVECTOR_H_
#include "core/util/tVector.h"
#endif
namespace Compiler
{
@ -49,7 +58,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 +69,7 @@ namespace Compiler
OP_CMPLT,
OP_CMPLE,
OP_CMPNE,
OP_XOR,
OP_XOR, // 20
OP_MOD,
OP_BITAND,
OP_BITOR,
@ -71,7 +80,7 @@ namespace Compiler
OP_SHR,
OP_SHL,
OP_AND,
OP_OR,
OP_OR, // 30
OP_ADD,
OP_SUB,
@ -84,7 +93,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 +106,7 @@ namespace Compiler
OP_SETCUROBJECT_INTERNAL,
OP_SETCURFIELD,
OP_SETCURFIELD_ARRAY,
OP_SETCURFIELD_ARRAY, // 50
OP_SETCURFIELD_TYPE,
OP_LOADFIELD_UINT,
@ -110,7 +119,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 +130,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 +142,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 +156,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,12 +227,19 @@ namespace Compiler
//------------------------------------------------------------
StringTableEntry U32toSTE(U32 u);
inline StringTableEntry CodeToSTE(U32 *code, U32 ip)
{
#ifdef TORQUE_CPU_X64
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();
@ -241,9 +257,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();
@ -254,4 +267,170 @@ 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<U32> mFixList;
Vector<U32> mFixStack;
Vector<bool> mFixLoopStack;
Vector<PatchEntry> mPatchList;
/// }
Vector<U32> mBreakLines; ///< Line numbers
public:
CodeStream() : mCode(0), mCodeHead(NULL), mCodePos(0)
{
}
~CodeStream()
{
reset();
if (mCode)
{
dFree(mCode->data);
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<mFixLoopStack.size(); i++)
{
if (mFixLoopStack[i])
return true;
}
return false;
}
inline U32 emitFix(FixType type)
{
U32 *ptr = (U32*)allocCode(4);
*ptr = (U32)type;
#ifdef DEBUG_CODESTREAM
printf("code[%u] = [FIX:%u]\n", mCodePos, (U32)type);
#endif
mFixList.push_back(mCodePos);
mFixList.push_back((U32)type);
return mCodePos++;
}
inline void pushFixScope(bool isLoop)
{
mFixStack.push_back(mFixList.size());
mFixLoopStack.push_back(isLoop);
}
inline void popFixScope()
{
AssertFatal(mFixStack.size() > 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

View file

@ -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 - 46->47 64bit support
DSOVersion = 47,
MaxLineLength = 512, ///< Maximum length of a line of console input.
MaxDataTypes = 256 ///< Maximum number of registered data types.

View file

@ -109,7 +109,7 @@ static const F32 F32_MAX = F32(3.402823466e+38F); ///< Constant
#endif
/// Integral type matching the host's memory address width.
#ifdef TORQUE_64BITS
#ifdef TORQUE_CPU_X64
typedef U64 MEM_ADDRESS;
#else
typedef U32 MEM_ADDRESS;