summaryrefslogtreecommitdiffstats
path: root/generic/tclDisassemble.c
diff options
context:
space:
mode:
authordkf <donal.k.fellows@manchester.ac.uk>2013-06-20 11:05:20 (GMT)
committerdkf <donal.k.fellows@manchester.ac.uk>2013-06-20 11:05:20 (GMT)
commit2859532759626d4782896f4c151bf58a668da85b (patch)
treef14745f2116873e0bc99ff6fd376da56bb7e42cf /generic/tclDisassemble.c
parentccccb754c0f55dc8e8250ab8c3a2019c96c6add2 (diff)
downloadtcl-2859532759626d4782896f4c151bf58a668da85b.zip
tcl-2859532759626d4782896f4c151bf58a668da85b.tar.gz
tcl-2859532759626d4782896f4c151bf58a668da85b.tar.bz2
Properly encode more operand types to reduce the number of special cases in the disassembler.
Diffstat (limited to 'generic/tclDisassemble.c')
-rw-r--r--generic/tclDisassemble.c164
1 files changed, 90 insertions, 74 deletions
diff --git a/generic/tclDisassemble.c b/generic/tclDisassemble.c
index 7f0b11a..c7072ee 100644
--- a/generic/tclDisassemble.c
+++ b/generic/tclDisassemble.c
@@ -482,42 +482,52 @@ FormatInstruction(
switch (instDesc->opTypes[i]) {
case OPERAND_INT1:
opnd = TclGetInt1AtPtr(pc+numBytes); numBytes++;
- if (opCode == INST_JUMP1 || opCode == INST_JUMP_TRUE1
- || opCode == INST_JUMP_FALSE1) {
- sprintf(suffixBuffer, "pc %u", pcOffset+opnd);
- }
Tcl_AppendPrintfToObj(bufferObj, "%+d ", opnd);
break;
case OPERAND_INT4:
opnd = TclGetInt4AtPtr(pc+numBytes); numBytes += 4;
- if (opCode == INST_JUMP4 || opCode == INST_JUMP_TRUE4
- || opCode == INST_JUMP_FALSE4) {
- sprintf(suffixBuffer, "pc %u", pcOffset+opnd);
- } else if (opCode == INST_START_CMD) {
- sprintf(suffixBuffer, "next cmd at pc %u", pcOffset+opnd);
- }
Tcl_AppendPrintfToObj(bufferObj, "%+d ", opnd);
break;
case OPERAND_UINT1:
opnd = TclGetUInt1AtPtr(pc+numBytes); numBytes++;
- if (opCode == INST_PUSH1) {
- suffixObj = codePtr->objArrayPtr[opnd];
- }
Tcl_AppendPrintfToObj(bufferObj, "%u ", (unsigned) opnd);
break;
- case OPERAND_AUX4:
case OPERAND_UINT4:
opnd = TclGetUInt4AtPtr(pc+numBytes); numBytes += 4;
- if (opCode == INST_PUSH4) {
- suffixObj = codePtr->objArrayPtr[opnd];
- } else if (opCode == INST_START_CMD && opnd != 1) {
+ if (opCode == INST_START_CMD) {
sprintf(suffixBuffer+strlen(suffixBuffer),
", %u cmds start here", opnd);
}
Tcl_AppendPrintfToObj(bufferObj, "%u ", (unsigned) opnd);
- if (instDesc->opTypes[i] == OPERAND_AUX4) {
- auxPtr = &codePtr->auxDataArrayPtr[opnd];
+ break;
+ case OPERAND_OFFSET1:
+ opnd = TclGetInt1AtPtr(pc+numBytes); numBytes++;
+ sprintf(suffixBuffer, "pc %u", pcOffset+opnd);
+ Tcl_AppendPrintfToObj(bufferObj, "%+d ", opnd);
+ break;
+ case OPERAND_OFFSET4:
+ opnd = TclGetInt4AtPtr(pc+numBytes); numBytes += 4;
+ if (opCode == INST_START_CMD) {
+ sprintf(suffixBuffer, "next cmd at pc %u", pcOffset+opnd);
+ } else {
+ sprintf(suffixBuffer, "pc %u", pcOffset+opnd);
}
+ Tcl_AppendPrintfToObj(bufferObj, "%+d ", opnd);
+ break;
+ case OPERAND_LIT1:
+ opnd = TclGetUInt1AtPtr(pc+numBytes); numBytes++;
+ suffixObj = codePtr->objArrayPtr[opnd];
+ Tcl_AppendPrintfToObj(bufferObj, "%u ", (unsigned) opnd);
+ break;
+ case OPERAND_LIT4:
+ opnd = TclGetUInt4AtPtr(pc+numBytes); numBytes += 4;
+ suffixObj = codePtr->objArrayPtr[opnd];
+ Tcl_AppendPrintfToObj(bufferObj, "%u ", (unsigned) opnd);
+ break;
+ case OPERAND_AUX4:
+ opnd = TclGetUInt4AtPtr(pc+numBytes); numBytes += 4;
+ Tcl_AppendPrintfToObj(bufferObj, "%u ", (unsigned) opnd);
+ auxPtr = &codePtr->auxDataArrayPtr[opnd];
break;
case OPERAND_IDX4:
opnd = TclGetInt4AtPtr(pc+numBytes); numBytes += 4;
@@ -896,54 +906,67 @@ DisassembleByteCodeAsDicts(
instructions = Tcl_NewObj();
for (pc=codePtr->codeStart; pc<codePtr->codeStart+codePtr->numCodeBytes;){
const InstructionDesc *instDesc = &tclInstructionTable[*pc];
+ int address = pc - codePtr->codeStart;
inst = Tcl_NewObj();
- Tcl_ListObjAppendElement(NULL, inst,
- Tcl_NewStringObj(instDesc->name, -1));
+ Tcl_ListObjAppendElement(NULL, inst, Tcl_NewStringObj(
+ instDesc->name, -1));
opnd = pc + 1;
for (i=0 ; i<instDesc->numOperands ; i++) {
switch (instDesc->opTypes[i]) {
case OPERAND_INT1:
val = TclGetInt1AtPtr(opnd);
opnd += 1;
- if (*pc == INST_JUMP1 || *pc == INST_JUMP_TRUE1
- || *pc == INST_JUMP_FALSE1) {
- Tcl_ListObjAppendElement(NULL, inst, Tcl_ObjPrintf(
- "pc %d", pc+val-codePtr->codeStart));
- } else {
- Tcl_ListObjAppendElement(NULL, inst, Tcl_NewIntObj(val));
- }
- break;
+ goto formatNumber;
+ case OPERAND_UINT1:
+ val = TclGetUInt1AtPtr(opnd);
+ opnd += 1;
+ goto formatNumber;
case OPERAND_INT4:
val = TclGetInt4AtPtr(opnd);
opnd += 4;
- if (*pc == INST_JUMP4 || *pc == INST_JUMP_TRUE4
- || *pc == INST_JUMP_FALSE4 || *pc == INST_START_CMD) {
- Tcl_ListObjAppendElement(NULL, inst, Tcl_ObjPrintf(
- "pc %d", pc+val-codePtr->codeStart));
- } else {
- Tcl_ListObjAppendElement(NULL, inst, Tcl_NewIntObj(val));
- }
+ goto formatNumber;
+ case OPERAND_UINT4:
+ val = TclGetUInt4AtPtr(opnd);
+ opnd += 4;
+ formatNumber:
+ Tcl_ListObjAppendElement(NULL, inst, Tcl_NewIntObj(val));
break;
- case OPERAND_UINT1:
+
+ case OPERAND_OFFSET1:
+ val = TclGetInt1AtPtr(opnd);
+ opnd += 1;
+ goto formatAddress;
+ case OPERAND_OFFSET4:
+ val = TclGetInt4AtPtr(opnd);
+ opnd += 4;
+ formatAddress:
+ Tcl_ListObjAppendElement(NULL, inst, Tcl_ObjPrintf(
+ "pc %d", address + val));
+ break;
+
+ case OPERAND_LIT1:
val = TclGetUInt1AtPtr(opnd);
opnd += 1;
- if (*pc == INST_PUSH1) {
- Tcl_ListObjAppendElement(NULL, inst, Tcl_ObjPrintf(
- "@%d", val));
- } else {
- Tcl_ListObjAppendElement(NULL, inst, Tcl_NewIntObj(val));
- }
+ goto formatLiteral;
+ case OPERAND_LIT4:
+ val = TclGetUInt4AtPtr(opnd);
+ opnd += 4;
+ formatLiteral:
+ Tcl_ListObjAppendElement(NULL, inst, Tcl_ObjPrintf(
+ "@%d", val));
break;
- case OPERAND_UINT4:
+
+ case OPERAND_LVT1:
+ val = TclGetUInt1AtPtr(opnd);
+ opnd += 1;
+ goto formatVariable;
+ case OPERAND_LVT4:
val = TclGetUInt4AtPtr(opnd);
opnd += 4;
- if (*pc == INST_PUSH4) {
- Tcl_ListObjAppendElement(NULL, inst, Tcl_ObjPrintf(
- "@%d", val));
- } else {
- Tcl_ListObjAppendElement(NULL, inst, Tcl_NewIntObj(val));
- }
+ formatVariable:
+ Tcl_ListObjAppendElement(NULL, inst, Tcl_ObjPrintf(
+ "%%%d", val));
break;
case OPERAND_IDX4:
val = TclGetInt4AtPtr(opnd);
@@ -952,37 +975,24 @@ DisassembleByteCodeAsDicts(
Tcl_ListObjAppendElement(NULL, inst, Tcl_ObjPrintf(
".%d", val));
} else if (val == -2) {
- Tcl_ListObjAppendElement(NULL, inst,
- Tcl_NewStringObj(".end", -1));
+ Tcl_ListObjAppendElement(NULL, inst, Tcl_NewStringObj(
+ ".end", -1));
} else {
- Tcl_ListObjAppendElement(NULL, inst,
- Tcl_ObjPrintf(".end-%d", -2-val));
+ Tcl_ListObjAppendElement(NULL, inst, Tcl_ObjPrintf(
+ ".end-%d", -2-val));
}
break;
- case OPERAND_LVT1:
- val = TclGetUInt1AtPtr(opnd);
- opnd += 1;
- Tcl_ListObjAppendElement(NULL, inst,
- Tcl_ObjPrintf("%%%d", val));
- break;
- case OPERAND_LVT4:
- val = TclGetUInt4AtPtr(opnd);
- opnd += 4;
- Tcl_ListObjAppendElement(NULL, inst,
- Tcl_ObjPrintf("%%%d", val));
- break;
case OPERAND_AUX4:
val = TclGetInt4AtPtr(opnd);
opnd += 4;
- Tcl_ListObjAppendElement(NULL, inst,
- Tcl_ObjPrintf("?%d", val));
+ Tcl_ListObjAppendElement(NULL, inst, Tcl_ObjPrintf(
+ "?%d", val));
break;
case OPERAND_NONE:
Tcl_Panic("opcode %d with more than zero 'no' operands", *pc);
}
}
- Tcl_DictObjPut(NULL, instructions,
- Tcl_NewIntObj(pc - codePtr->codeStart), inst);
+ Tcl_DictObjPut(NULL, instructions, Tcl_NewIntObj(address), inst);
pc += instDesc->numBytes;
}
@@ -1039,18 +1049,23 @@ DisassembleByteCodeAsDicts(
/*
* Get the command information from the bytecode.
+ *
+ * The way these are encoded in the bytecode is non-trivial; the Decode
+ * macro (which updates its argument and returns the next decoded value)
+ * handles this so that the rest of the code does not.
*/
+#define Decode(ptr) \
+ ((TclGetUInt1AtPtr(ptr) == 0xFF) \
+ ? ((ptr)+=5 , TclGetInt4AtPtr((ptr)-4)) \
+ : ((ptr)+=1 , TclGetInt1AtPtr((ptr)-1)))
+
commands = Tcl_NewObj();
codeOffPtr = codePtr->codeDeltaStart;
codeLenPtr = codePtr->codeLengthStart;
srcOffPtr = codePtr->srcDeltaStart;
srcLenPtr = codePtr->srcLengthStart;
codeOffset = sourceOffset = 0;
-#define Decode(ptr) \
- ((TclGetUInt1AtPtr(ptr) == 0xFF) \
- ? ((ptr)+=5,TclGetInt4AtPtr((ptr)-4)) \
- : ((ptr)+=1,TclGetInt1AtPtr((ptr)-1)))
for (i=0 ; i<codePtr->numCommands ; i++) {
Tcl_Obj *cmd;
@@ -1077,6 +1092,7 @@ DisassembleByteCodeAsDicts(
Tcl_NewStringObj(codePtr->source+sourceOffset, sourceLength));
Tcl_ListObjAppendElement(NULL, commands, cmd);
}
+
#undef Decode
/*