2009-06-02 15:21:42 +00:00
# !/usr/bin/tcl
#
# This script makes modifications to the vdbe.c source file which reduce
# the amount of stack space required by the sqlite3VdbeExec() routine.
#
# The modifications performed by this script are optional. The vdbe.c
# source file will compile correctly with and without the modifications
# performed by this script. And all routines within vdbe.c will compute
# the same result. The modifications made by this script merely help
# the C compiler to generate code for sqlite3VdbeExec() that uses less
# stack space.
#
# Script usage:
#
# mv vdbe.c vdbe.c.template
2013-12-11 00:59:10 +00:00
# tclsh vdbe-compress.tcl $CFLAGS <vdbe.c.template >vdbe.c
2009-06-02 15:21:42 +00:00
#
# Modifications made:
#
# All modifications are within the sqlite3VdbeExec() function. The
# modifications seek to reduce the amount of stack space allocated by
# this routine by moving local variable declarations out of individual
# opcode implementations and into a single large union. The union contains
# a separate structure for each opcode and that structure contains the
# local variables used by that opcode. In this way, the total amount
# of stack space required by sqlite3VdbeExec() is reduced from the
# sum of all local variables to the maximum of the local variable space
# required for any single opcode.
#
# In order to be recognized by this script, local variables must appear
# on the first line after the open curly-brace that begins a new opcode
# implementation. Local variables must not have initializers, though they
# may be commented.
#
# The union definition is inserted in place of a special marker comment
# in the preamble to the sqlite3VdbeExec() implementation.
#
# ############################################################################
#
set beforeUnion { } ; # C code before union
set unionDef { } ; # C code of the union
set afterUnion { } ; # C code after the union
set sCtr 0 ; # Context counter
2013-12-11 00:59:10 +00:00
# If the SQLITE_SMALL_STACK compile-time option is missing, then
# this transformation becomes a no-op.
#
if { ! [ regexp { SQLITE_SMALL_STACK } $argv ] } {
while { ! [ eof stdin] } {
puts [ gets stdin]
}
exit
}
2009-06-02 15:21:42 +00:00
# Read program text up to the spot where the union should be
# inserted.
#
while { ! [ eof stdin] } {
set line [ gets stdin]
if { [ regexp { INSERT STACK UNION HERE} $line ] } break
append beforeUnion $line \ n
}
# Process the remaining text. Build up the union definition as we go.
#
set vlist { }
set seenDecl 0
2022-02-03 14:37:06 +00:00
set namechars { abcefghjklmnopqrstuvwxyz }
2009-06-02 15:21:42 +00:00
set nnc [ string length $namechars ]
while { ! [ eof stdin] } {
set line [ gets stdin]
if { [ regexp " ^ c a s e ( O P _ \\ w + ) : \173 " $line all operator] } {
append afterUnion $line \ n
set vlist { }
while { ! [ eof stdin] } {
set line [ gets stdin]
2009-06-02 16:06:03 +00:00
if { [ regexp { ^ + ( const ) ? \ w + \ ** ( \ w + ) ( \ [ . * \ ] ) ? ; } $line \
2009-06-02 15:21:42 +00:00
all constKeyword vname notused1] } {
if { ! $seenDecl } {
set sname { }
append sname [ string index $namechars [ expr { $sCtr / $nnc } ] ]
append sname [ string index $namechars [ expr { $sCtr % $nnc } ] ]
incr sCtr
append unionDef " s t r u c t $ { o p e r a t o r } _ s t a c k _ v a r s \173 \n "
append afterUnion \
" # i f 0 / * l o c a l v a r i a b l e s m o v e d i n t o u . $ s n a m e * / \n "
set seenDecl 1
}
append unionDef " $ l i n e \n "
append afterUnion $line \ n
lappend vlist $vname
2012-09-18 13:20:13 +00:00
} elseif { [ regexp { ^ # (if|endif)} $line] && [llength $vlist]>0} {
append unionDef " $ l i n e \n "
append afterUnion $line \ n
2009-06-02 15:21:42 +00:00
} else {
break
}
}
if { $seenDecl } {
append unionDef " \175 $ s n a m e ; \n "
append afterUnion " # e n d i f / * l o c a l v a r i a b l e s m o v e d i n t o u . $ s n a m e * / \n "
}
set seenDecl 0
}
if { [ regexp " ^ \175 " $line ] } {
append afterUnion $line \ n
set vlist { }
} elseif { [ llength $vlist ] > 0 } {
append line " "
foreach v $vlist {
regsub - all " ( \[ ^ a - z A - Z 0 - 9 > . \] ) $ { v } ( \\ W ) " $line " \\ 1 u . $ s n a m e . $ v \\ 2 " line
2009-09-01 12:16:01 +00:00
regsub - all " ( \[ ^ a - z A - Z 0 - 9 > . \] ) $ { v } ( \\ W ) " $line " \\ 1 u . $ s n a m e . $ v \\ 2 " line
2014-10-16 11:45:14 +00:00
# The expressions above fail to catch instance of variable "abc" in
# expressions like (32>abc). The following expression makes those
# substitutions.
regsub - all " ( \[ ^ - \] ) > $ { v } ( \\ W ) " $line " \\ 1 > u . $ s n a m e . $ v \\ 2 " line
2009-06-02 15:21:42 +00:00
}
append afterUnion [ string trimright $line ] \ n
} elseif { $line == " " && [ eof stdin] } {
# no-op
} else {
append afterUnion $line \ n
}
}
# Output the resulting text.
#
puts - nonewline $beforeUnion
puts " / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * "
puts " * * A u t o m a t i c a l l y g e n e r a t e d c o d e "
puts " * * "
puts " * * T h e f o l l o w i n g u n i o n i s a u t o m a t i c a l l y g e n e r a t e d b y t h e "
puts " * * v d b e - c o m p r e s s . t c l s c r i p t . T h e p u r p o s e o f t h i s u n i o n i s t o "
puts " * * r e d u c e t h e a m o u n t o f s t a c k s p a c e r e q u i r e d b y t h i s f u n c t i o n . "
puts " * * S e e c o m m e n t s i n t h e v d b e - c o m p r e s s . t c l s c r i p t f o r d e t a i l s . "
puts " * / "
puts " u n i o n v d b e E x e c U n i o n \173 "
puts - nonewline $unionDef
puts " \175 u ; "
puts " / * E n d a u t o m a t i c a l l y g e n e r a t e d c o d e "
puts " * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * / "
puts - nonewline $afterUnion