blob: 9477f4afe62a4aaaec5265faf6f3a96d0af66741 [file] [log] [blame]
drh856c1032009-06-02 15:21:42 +00001#!/usr/bin/tcl
2#
3# This script makes modifications to the vdbe.c source file which reduce
4# the amount of stack space required by the sqlite3VdbeExec() routine.
5#
6# The modifications performed by this script are optional. The vdbe.c
7# source file will compile correctly with and without the modifications
8# performed by this script. And all routines within vdbe.c will compute
9# the same result. The modifications made by this script merely help
10# the C compiler to generate code for sqlite3VdbeExec() that uses less
11# stack space.
12#
13# Script usage:
14#
15# mv vdbe.c vdbe.c.template
drh2dc06482013-12-11 00:59:10 +000016# tclsh vdbe-compress.tcl $CFLAGS <vdbe.c.template >vdbe.c
drh856c1032009-06-02 15:21:42 +000017#
18# Modifications made:
19#
20# All modifications are within the sqlite3VdbeExec() function. The
21# modifications seek to reduce the amount of stack space allocated by
22# this routine by moving local variable declarations out of individual
23# opcode implementations and into a single large union. The union contains
24# a separate structure for each opcode and that structure contains the
25# local variables used by that opcode. In this way, the total amount
26# of stack space required by sqlite3VdbeExec() is reduced from the
27# sum of all local variables to the maximum of the local variable space
28# required for any single opcode.
29#
30# In order to be recognized by this script, local variables must appear
31# on the first line after the open curly-brace that begins a new opcode
32# implementation. Local variables must not have initializers, though they
33# may be commented.
34#
35# The union definition is inserted in place of a special marker comment
36# in the preamble to the sqlite3VdbeExec() implementation.
37#
38#############################################################################
39#
40set beforeUnion {} ;# C code before union
41set unionDef {} ;# C code of the union
42set afterUnion {} ;# C code after the union
43set sCtr 0 ;# Context counter
44
drh2dc06482013-12-11 00:59:10 +000045# If the SQLITE_SMALL_STACK compile-time option is missing, then
46# this transformation becomes a no-op.
47#
48if {![regexp {SQLITE_SMALL_STACK} $argv]} {
49 while {![eof stdin]} {
50 puts [gets stdin]
51 }
52 exit
53}
54
drh856c1032009-06-02 15:21:42 +000055# Read program text up to the spot where the union should be
56# inserted.
57#
58while {![eof stdin]} {
59 set line [gets stdin]
60 if {[regexp {INSERT STACK UNION HERE} $line]} break
61 append beforeUnion $line\n
62}
63
64# Process the remaining text. Build up the union definition as we go.
65#
66set vlist {}
67set seenDecl 0
68set namechars {abcdefghijklmnopqrstuvwxyz}
69set nnc [string length $namechars]
70while {![eof stdin]} {
71 set line [gets stdin]
72 if {[regexp "^case (OP_\\w+): \173" $line all operator]} {
73 append afterUnion $line\n
74 set vlist {}
75 while {![eof stdin]} {
76 set line [gets stdin]
drhc54a6172009-06-02 16:06:03 +000077 if {[regexp {^ +(const )?\w+ \**(\w+)(\[.*\])?;} $line \
drh856c1032009-06-02 15:21:42 +000078 all constKeyword vname notused1]} {
79 if {!$seenDecl} {
80 set sname {}
81 append sname [string index $namechars [expr {$sCtr/$nnc}]]
82 append sname [string index $namechars [expr {$sCtr%$nnc}]]
83 incr sCtr
84 append unionDef " struct ${operator}_stack_vars \173\n"
85 append afterUnion \
86 "#if 0 /* local variables moved into u.$sname */\n"
87 set seenDecl 1
88 }
89 append unionDef " $line\n"
90 append afterUnion $line\n
91 lappend vlist $vname
drh3a949872012-09-18 13:20:13 +000092 } elseif {[regexp {^#(if|endif)} $line] && [llength $vlist]>0} {
93 append unionDef "$line\n"
94 append afterUnion $line\n
drh856c1032009-06-02 15:21:42 +000095 } else {
96 break
97 }
98 }
99 if {$seenDecl} {
100 append unionDef " \175 $sname;\n"
101 append afterUnion "#endif /* local variables moved into u.$sname */\n"
102 }
103 set seenDecl 0
104 }
105 if {[regexp "^\175" $line]} {
106 append afterUnion $line\n
107 set vlist {}
108 } elseif {[llength $vlist]>0} {
109 append line " "
110 foreach v $vlist {
111 regsub -all "(\[^a-zA-Z0-9>.\])${v}(\\W)" $line "\\1u.$sname.$v\\2" line
dan65a7cd12009-09-01 12:16:01 +0000112 regsub -all "(\[^a-zA-Z0-9>.\])${v}(\\W)" $line "\\1u.$sname.$v\\2" line
danfacd5fd2014-10-16 11:45:14 +0000113
114 # The expressions above fail to catch instance of variable "abc" in
115 # expressions like (32>abc). The following expression makes those
116 # substitutions.
117 regsub -all "(\[^-\])>${v}(\\W)" $line "\\1>u.$sname.$v\\2" line
drh856c1032009-06-02 15:21:42 +0000118 }
119 append afterUnion [string trimright $line]\n
120 } elseif {$line=="" && [eof stdin]} {
121 # no-op
122 } else {
123 append afterUnion $line\n
124 }
125}
126
127# Output the resulting text.
128#
129puts -nonewline $beforeUnion
130puts " /********************************************************************"
131puts " ** Automatically generated code"
132puts " **"
133puts " ** The following union is automatically generated by the"
134puts " ** vdbe-compress.tcl script. The purpose of this union is to"
135puts " ** reduce the amount of stack space required by this function."
136puts " ** See comments in the vdbe-compress.tcl script for details."
137puts " */"
138puts " union vdbeExecUnion \173"
139puts -nonewline $unionDef
140puts " \175 u;"
141puts " /* End automatically generated code"
142puts " ********************************************************************/"
143puts -nonewline $afterUnion