1#!/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 16# tclsh vdbe-compress.tcl $CFLAGS <vdbe.c.template >vdbe.c 17# 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 45# 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 55# 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 {abcefghjklmnopqrstuvwxyz} 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] 77 if {[regexp {^ +(const )?\w+ \**(\w+)(\[.*\])?;} $line \ 78 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 92 } elseif {[regexp {^#(if|endif)} $line] && [llength $vlist]>0} { 93 append unionDef "$line\n" 94 append afterUnion $line\n 95 } 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 112 regsub -all "(\[^a-zA-Z0-9>.\])${v}(\\W)" $line "\\1u.$sname.$v\\2" line 113 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 118 } 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 144