Home | History | Annotate | Download | only in tool
      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 <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 #
     40 set beforeUnion {}   ;# C code before union
     41 set unionDef {}      ;# C code of the union
     42 set afterUnion {}    ;# C code after the union
     43 set sCtr 0           ;# Context counter
     44 
     45 # Read program text up to the spot where the union should be
     46 # inserted.
     47 #
     48 while {![eof stdin]} {
     49   set line [gets stdin]
     50   if {[regexp {INSERT STACK UNION HERE} $line]} break
     51   append beforeUnion $line\n
     52 }
     53 
     54 # Process the remaining text.  Build up the union definition as we go.
     55 #
     56 set vlist {}
     57 set seenDecl 0
     58 set namechars {abcdefghijklmnopqrstuvwxyz}
     59 set nnc [string length $namechars]
     60 while {![eof stdin]} {
     61   set line [gets stdin]
     62   if {[regexp "^case (OP_\\w+): \173" $line all operator]} {
     63     append afterUnion $line\n
     64     set vlist {}
     65     while {![eof stdin]} {
     66       set line [gets stdin]
     67       if {[regexp {^ +(const )?\w+ \**(\w+)(\[.*\])?;} $line \
     68            all constKeyword vname notused1]} {
     69         if {!$seenDecl} {
     70           set sname {}
     71           append sname [string index $namechars [expr {$sCtr/$nnc}]]
     72           append sname [string index $namechars [expr {$sCtr%$nnc}]]
     73           incr sCtr
     74           append unionDef "    struct ${operator}_stack_vars \173\n"
     75           append afterUnion \
     76              "#if 0  /* local variables moved into u.$sname */\n"
     77           set seenDecl 1
     78         }
     79         append unionDef "    $line\n"
     80         append afterUnion $line\n
     81         lappend vlist $vname
     82       } else {
     83         break
     84       }
     85     }
     86     if {$seenDecl} {
     87       append unionDef   "    \175 $sname;\n"
     88       append afterUnion "#endif /* local variables moved into u.$sname */\n"
     89     }
     90     set seenDecl 0
     91   }
     92   if {[regexp "^\175" $line]} {
     93     append afterUnion $line\n
     94     set vlist {}
     95   } elseif {[llength $vlist]>0} {
     96     append line " "
     97     foreach v $vlist {
     98       regsub -all "(\[^a-zA-Z0-9>.\])${v}(\\W)" $line "\\1u.$sname.$v\\2" line
     99       regsub -all "(\[^a-zA-Z0-9>.\])${v}(\\W)" $line "\\1u.$sname.$v\\2" line
    100     }
    101     append afterUnion [string trimright $line]\n
    102   } elseif {$line=="" && [eof stdin]} {
    103     # no-op
    104   } else {
    105     append afterUnion $line\n
    106   }
    107 }
    108 
    109 # Output the resulting text.
    110 #
    111 puts -nonewline $beforeUnion
    112 puts "  /********************************************************************"
    113 puts "  ** Automatically generated code"
    114 puts "  **"
    115 puts "  ** The following union is automatically generated by the"
    116 puts "  ** vdbe-compress.tcl script.  The purpose of this union is to"
    117 puts "  ** reduce the amount of stack space required by this function."
    118 puts "  ** See comments in the vdbe-compress.tcl script for details."
    119 puts "  */"
    120 puts "  union vdbeExecUnion \173"
    121 puts -nonewline $unionDef
    122 puts "  \175 u;"
    123 puts "  /* End automatically generated code"
    124 puts "  ********************************************************************/"
    125 puts -nonewline $afterUnion
    126