diff options
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | generic/tclAssembly.c | 238 | ||||
-rw-r--r-- | generic/tclAssembly.h | 205 | ||||
-rw-r--r-- | unix/Makefile.in | 3 |
4 files changed, 245 insertions, 209 deletions
@@ -1,3 +1,11 @@ +2010-10-23 Kevin B. Kenny <kennykb@acm.org> + + [dogeen-assembler-branch] + * tclAssembly.h (removed): + Removed file that was included in only one + source file. + * tclAssembly.c: Inlined tclAssembly.h. + 2010-10-17 Alexandre Ferrieux <ferrieux@users.sourceforge.net> * doc/info.n : [Patch 2995655] : 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 */ diff --git a/generic/tclAssembly.h b/generic/tclAssembly.h deleted file mode 100644 index 182e210..0000000 --- a/generic/tclAssembly.h +++ /dev/null @@ -1,205 +0,0 @@ -#ifndef _TCL_ASSEMBLY -#define _TCL_ASSEMBLY 1 - -#include "tclCompile.h" - -/* 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; - -typedef struct CodeRange { - int startOffset; /* Start offset in the bytecode array */ - int endOffset; /* End offset in the bytecode array */ -} CodeRange; - -/* - * Structure that defines a basic block - a linear sequence of bytecode - * instructions with no jumps in or out. - */ - -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; - -MODULE_SCOPE int TclAssembleCode(CompileEnv* compEnv, const char* codePtr, - int codeLen, int flags); - -#endif diff --git a/unix/Makefile.in b/unix/Makefile.in index 11ca16c..7ddd2a7 100644 --- a/unix/Makefile.in +++ b/unix/Makefile.in @@ -4,7 +4,7 @@ # "./configure", which is a configuration script generated by the "autoconf" # program (constructs like "@foo@" will get replaced in the actual Makefile. # -# RCS: @(#) $Id: Makefile.in,v 1.306.2.3 2010/09/28 15:43:01 kennykb Exp $ +# RCS: @(#) $Id: Makefile.in,v 1.306.2.4 2010/10/23 16:14:24 kennykb Exp $ VERSION = @TCL_VERSION@ MAJOR_VERSION = @TCL_MAJOR_VERSION@ @@ -363,7 +363,6 @@ TCL_DECLS = \ GENERIC_HDRS = \ $(GENERIC_DIR)/tcl.h \ - $(GENERIC_DIR)/tclAssembly.h \ $(GENERIC_DIR)/tclDecls.h \ $(GENERIC_DIR)/tclInt.h \ $(GENERIC_DIR)/tclIntDecls.h \ |