summaryrefslogtreecommitdiff
path: root/tool/vdbe-compress.tcl
blob: a349830bcf5f3731ea6543ef89e25f9a9bd1bad4 (plain)
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
130
131
132
133
134
135
136
137
138
#!/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
#          tclsh vdbe-compress.tcl $CFLAGS <vdbe.c.template >vdbe.c
#
# 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

# 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
}

# 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
set namechars {abcdefghijklmnopqrstuvwxyz}
set nnc [string length $namechars]
while {![eof stdin]} {
  set line [gets stdin]
  if {[regexp "^case (OP_\\w+): \173" $line all operator]} {
    append afterUnion $line\n
    set vlist {}
    while {![eof stdin]} {
      set line [gets stdin]
      if {[regexp {^ +(const )?\w+ \**(\w+)(\[.*\])?;} $line \
           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 "    struct ${operator}_stack_vars \173\n"
          append afterUnion \
             "#if 0  /* local variables moved into u.$sname */\n"
          set seenDecl 1
        }
        append unionDef "    $line\n"
        append afterUnion $line\n
        lappend vlist $vname
      } elseif {[regexp {^#(if|endif)} $line] && [llength $vlist]>0} {
        append unionDef "$line\n"
        append afterUnion $line\n
      } else {
        break
      }
    }
    if {$seenDecl} {
      append unionDef   "    \175 $sname;\n"
      append afterUnion "#endif /* local variables moved into u.$sname */\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-zA-Z0-9>.\])${v}(\\W)" $line "\\1u.$sname.$v\\2" line
      regsub -all "(\[^a-zA-Z0-9>.\])${v}(\\W)" $line "\\1u.$sname.$v\\2" line
    }
    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 "  ** Automatically generated code"
puts "  **"
puts "  ** The following union is automatically generated by the"
puts "  ** vdbe-compress.tcl script.  The purpose of this union is to"
puts "  ** reduce the amount of stack space required by this function."
puts "  ** See comments in the vdbe-compress.tcl script for details."
puts "  */"
puts "  union vdbeExecUnion \173"
puts -nonewline $unionDef
puts "  \175 u;"
puts "  /* End automatically generated code"
puts "  ********************************************************************/"
puts -nonewline $afterUnion