1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
#ifndef _TCL_ASSEMBLY
#define _TCL_ASSEMBLY 1
#include "tclCompile.h"
/*
* 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 */
int may_fall_thru; /* Flag == 1 if control passes from this
* block to its successor. */
int visited; /* Flag==1 if this block has been visited
* in the stack checker*/
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 */
} BasicBlock;
/* Source instruction type recognized by the assembler */
typedef enum TalInstType {
ASSEM_1BYTE, /* Fixed arity, 1-byte instruction */
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_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_REVERSE, /* REVERSE: 4-byte operand count, consumes N, produces N */
ASSEM_SINT1, /* One 1-byte signed-integer operand (INCR_STK_IMM) */
} 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 flags; /* Compilation flags (TCL_EVAL_DIRECT) */
} AssembleEnv;
MODULE_SCOPE int TclAssembleCode(CompileEnv* compEnv, const char* codePtr,
int codeLen, int flags);
#endif
|