diff options
author | Kevin B Kenny <kennykb@acm.org> | 2010-10-23 16:14:24 (GMT) |
---|---|---|
committer | Kevin B Kenny <kennykb@acm.org> | 2010-10-23 16:14:24 (GMT) |
commit | 8ebae5e9d270bca732c4b07bb2d264bd07d16806 (patch) | |
tree | a5b659ff56cac3f0722cd326601e228b8db201ea /generic/tclAssembly.c | |
parent | a8212a3142ffffc86cf0eb05606cae9116d2d337 (diff) | |
download | tcl-8ebae5e9d270bca732c4b07bb2d264bd07d16806.zip tcl-8ebae5e9d270bca732c4b07bb2d264bd07d16806.tar.gz tcl-8ebae5e9d270bca732c4b07bb2d264bd07d16806.tar.bz2 |
removed useless separation between tclAssembly.h and tclAssembly.c
Diffstat (limited to 'generic/tclAssembly.c')
-rw-r--r-- | generic/tclAssembly.c | 238 |
1 files changed, 236 insertions, 2 deletions
diff --git a/generic/tclAssembly.c b/generic/tclAssembly.c index ec9c9c1..c773ee0 100644 --- a/generic/tclAssembly.c +++ b/generic/tclAssembly.c @@ -1,8 +1,240 @@ +/* + * tclAssembly,c -- + * + * Assembler for Tcl bytecodes. + * + * This file contains the procedures that convert Tcl Assembly Language + * (TAL) to a sequence of bytecode instructions for the Tcl execution engine. + * + * Copyright (c) 2010 by Ozgur Dogan Ugurlu. + * Copyright (c) 2010 by Kevin B. Kenny. + * + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tclAssembly.c,v 1.1.2.15 2010/10/23 16:14:24 kennykb Exp $ + */ + +/*- + *- THINGS TO DO: + *- Rework jump handling to allow jump1, jumpTrue1, jumpFalse1 in the + *- forward direction + *- More instructions: + *- done - alternate exit point (affects stack and exception range checking) + *- break and continue - if exception ranges can be sorted out. + *- foreach_start4, foreach_step4 + *- returnImm, returnStk + *- expandStart, expandStkTop, invokeExpanded + *- dictFirst, dictNext, dictDone + *- dictUpdateStart, dictUpdateEnd + *- jumpTable + *- syntax (?) + *- returnCodeBranch + */ + #include "tclInt.h" #include "tclCompile.h" -#include "tclAssembly.h" #include "tclOOInt.h" +/* Structure that represents a range of instructions in the bytecode */ + +typedef struct CodeRange { + int startOffset; /* Start offset in the bytecode array */ + int endOffset; /* End offset in the bytecode array */ +} CodeRange; + +/* State identified for a basic block's catch context */ + +typedef enum BasicBlockCatchState { + BBCS_UNKNOWN = 0, /* Catch context has not yet been identified */ + BBCS_NONE, /* Block is outside of any catch */ + BBCS_INCATCH, /* Block is within a catch context */ + BBCS_DONECATCH, /* Block is nominally within a catch context + * but has passed a 'doneCatch' directive + * and wants exceptions to propagate. */ + BBCS_CAUGHT, /* Block is within a catch context and + * may be executed after an exception fires */ +} BasicBlockCatchState; + +/* + * Structure that defines a basic block - a linear sequence of bytecode + * instructions with no jumps in or out (including not changing the + * state of any exception range). + */ + +typedef struct BasicBlock { + + int startOffset; /* Instruction offset of the start of + * the block */ + int startLine; /* Line number in the input script of the + * instruction at the start of the block */ + int jumpLine; /* Line number in the input script of the + * 'jump' instruction that ends the block, + * or -1 if there is no jump */ + struct BasicBlock* predecessor; + /* Predecessor of this block in the + * spanning tree */ + struct BasicBlock * successor1; + /* BasicBlock structure of the following + * block: NULL at the end of the bytecode + * sequence or if the block ends in an + * unconditional jump */ + Tcl_Obj * jumpTarget; /* Jump target label if the jump target + * is unresolved */ + + int initialStackDepth; /* Absolute stack depth on entry */ + int minStackDepth; /* Low-water relative stack depth */ + int maxStackDepth; /* High-water relative stack depth */ + int finalStackDepth; /* Relative stack depth on exit */ + + enum BasicBlockCatchState catchState; + /* State of the block for 'catch' analysis */ + int catchDepth; /* Number of nested catches in which the + * basic block appears */ + struct BasicBlock* enclosingCatch; + /* BasicBlock structure of the last + * startCatch executed on a path to this + * block, or NULL if there is no + * enclosing catch */ + + int foreignExceptionBase; /* Base index of foreign exceptions */ + int foreignExceptionCount; /* Count of foreign exceptions */ + ExceptionRange* foreignExceptions; + /* ExceptionRange structures for + * exception ranges belonging to embedded + * scripts and expressions in this block */ + + int flags; /* Boolean flags */ + +} BasicBlock; + +/* Flags that pertain to a basic block */ + +enum BasicBlockFlags { + BB_VISITED = (1 << 0), /* Block has been visited in the current + * traversal */ + BB_FALLTHRU = (1 << 1), /* Control may pass from this block to + * a successor */ + BB_BEGINCATCH = (1 << 2), /* Block ends with a 'beginCatch' instruction, + * marking it as the start of a 'catch' + * sequence. The 'jumpTarget' is the exception + * exit from the catch block. */ + BB_DONECATCH = (1 << 3), /* Block commences with a 'doneCatch' + * directive, indicating that the program + * is finished with the body of a catch block. + */ + BB_ENDCATCH = (1 << 4), /* Block ends with an 'endCatch' instruction, + * unwinding the catch from the exception + * stack. */ +}; + +/* Source instruction type recognized by the assembler */ + +typedef enum TalInstType { + + ASSEM_1BYTE, /* Fixed arity, 1-byte instruction */ + ASSEM_BEGIN_CATCH, + /* Begin catch: one 4-byte jump offset to be converted + * to appropriate exception ranges */ + ASSEM_BOOL, /* One Boolean operand */ + ASSEM_BOOL_LVT4,/* One Boolean, one 4-byte LVT ref. */ + ASSEM_CONCAT1, /* 1-byte unsigned-integer operand count, must be + * strictly positive, consumes N, produces 1 */ + ASSEM_DICT_GET, /* 'dict get' and related - consumes N+1 operands, + * produces 1, N > 0 */ + ASSEM_DICT_SET, /* specifies key count and LVT index, consumes N+1 operands, + * produces 1, N > 0 */ + ASSEM_DICT_UNSET, + /* specifies key count and LVT index, consumes N operands, + * produces 1, N > 0 */ + ASSEM_DONECATCH,/* Directive indicating that the body of a catch block + * is complete. Generates no instructions, affects only + * the exception ranges. */ + ASSEM_END_CATCH,/* End catch. No args. Exception range popped from stack + * and stack pointer restored. */ + ASSEM_EVAL, /* 'eval' - evaluate a constant script (by compiling it + * in line with the assembly code! I love Tcl!) */ + ASSEM_INDEX, /* 4 byte operand, integer or end-integer */ + ASSEM_INVOKE, /* 1- or 4-byte operand count, must be strictly positive, + * consumes N, produces 1. */ + ASSEM_JUMP, /* Jump instructions */ + ASSEM_LABEL, /* The assembly directive that defines a label */ + ASSEM_LINDEX_MULTI, + /* 4-byte operand count, must be strictly positive, + * consumes N, produces 1 */ + ASSEM_LIST, /* 4-byte operand count, must be nonnegative, consumses N, + * produces 1 */ + ASSEM_LSET_FLAT,/* 4-byte operand count, must be >= 3, consumes N, + * produces 1 */ + ASSEM_LVT, /* One operand that references a local variable */ + ASSEM_LVT1, /* One 1-byte operand that references a local variable */ + ASSEM_LVT1_SINT1, + /* One 1-byte operand that references a local variable, + * one signed-integer 1-byte operand */ + ASSEM_LVT4, /* One 4-byte operand that references a local variable */ + ASSEM_OVER, /* OVER: 4-byte operand count, consumes N+1, produces N+2 */ + ASSEM_PUSH, /* one literal operand */ + ASSEM_REGEXP, /* One Boolean operand, but weird mapping to call flags */ + ASSEM_REVERSE, /* REVERSE: 4-byte operand count, consumes N, produces N */ + ASSEM_SINT1, /* One 1-byte signed-integer operand (INCR_STK_IMM) */ + ASSEM_SINT4_LVT4, + /* Signed 4-byte integer operand followed by LVT entry. + * Fixed arity */ +} TalInstType; + +/* Description of an instruction recognized by the assembler. */ + +typedef struct TalInstDesc { + const char *name; /* Name of instruction. */ + TalInstType instType; /* The type of instruction */ + int tclInstCode; /* Instruction code. For instructions having + * 1- and 4-byte variables, tclInstCode is + * ((1byte)<<8) || (4byte) */ + int operandsConsumed; /* Number of operands consumed by the + * operation, or INT_MIN if the operation + * is variadic */ + int operandsProduced; /* Number of operands produced by the + * operation. If negative, the operation + * has a net stack effect of + * -1-operandsProduced */ +} TalInstDesc; + +/* Description of a label in the assembly code */ + +typedef struct JumpLabel { + int isDefined; /* Flag == 1 if label is defined */ + int offset; /* Offset in the code where the label starts, + * or head of a linked list of jump target + * addresses if the label is undefined */ + BasicBlock* basicBlock; /* Basic block that begins at the label */ +} JumpLabel; + +/* Structure that holds the state of the assembler while generating code */ + +typedef struct AssembleEnv { + CompileEnv* envPtr; /* Compilation environment being used + * for code generation */ + Tcl_Parse* parsePtr; /* Parse of the current line of source */ + Tcl_HashTable labelHash; /* Hash table whose keys are labels and + * whose values are 'label' objects storing + * the code offsets of the labels. */ + + int cmdLine; /* Current line number within the assembly + * code */ + int* clNext; /* Invisible continuation line for + * [info frame] */ + + BasicBlock* head_bb; /* First basic block in the code */ + BasicBlock* curr_bb; /* Current basic block */ + + int maxDepth; /* Maximum stack depth encountered */ + + int curCatchDepth; /* Current depth of catches */ + int maxCatchDepth; /* Maximum depth of catches encountered */ + + int flags; /* Compilation flags (TCL_EVAL_DIRECT) */ +} AssembleEnv; + /* Static functions defined in this file */ static void AddBasicBlockRangeToErrorInfo(AssembleEnv*, BasicBlock*); @@ -56,6 +288,8 @@ static int StackCheckExit(AssembleEnv*); static void StackFreshCatches(AssembleEnv*, BasicBlock*, int, BasicBlock**, int*); static void SyncStackDepth(AssembleEnv*); +static int TclAssembleCode(CompileEnv* envPtr, const char* code, int codeLen, + int flags); static void UnstackExpiredCatches(CompileEnv*, BasicBlock*, int, BasicBlock**, int*); @@ -662,7 +896,7 @@ int TclCompileAssembleCmd( *----------------------------------------------------------------------------- */ -MODULE_SCOPE int +static int TclAssembleCode(CompileEnv *envPtr, /* Compilation environment that is to * receive the generated bytecode */ |