 4034931013
			
		
	
	4034931013
	
	
	
		
			
			With sqlite3 3110100, which is used in MaxScale, the the generation
of the used op-codes could sometime generate code that did not define
all opcodes. That resulted then in a compilation error like:
.../sqlite-bld-3110100/sqlite3.c: In function 'sqlite3VdbeExec':
.../sqlite-bld-3110100/sqlite3.c:75427:6: error: 'OP_Real' undeclared
                                          (first use in this function)
 case OP_Real: {            /* same as TK_FLOAT, out2 */
      ^
The reason seems to be that if a particular op-code was not used, the
generation stopped at that point:
    #define OP_Explain       160
    #define OP_NotUsed_161   161
With mkopcodeh.tcl from sqlite3 version 3200000, the generated code
looks like
    #define OP_NotUsed_161   161
    #define OP_Real          162 /* same as TK_FLOAT,
                                    synopsis: r[P2]=P4       */
and the code compiles.
Thus, mkopcodeh.tsl is updated from the newer sqlite3 version.
		
	
		
			
				
	
	
		
			272 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			Tcl
		
	
	
	
	
	
			
		
		
	
	
			272 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			Tcl
		
	
	
	
	
	
| #!/usr/bin/tclsh
 | |
| #
 | |
| # Generate the file opcodes.h.
 | |
| #
 | |
| # This TCL script scans a concatenation of the parse.h output file from the
 | |
| # parser and the vdbe.c source file in order to generate the opcodes numbers
 | |
| # for all opcodes.  
 | |
| #
 | |
| # The lines of the vdbe.c that we are interested in are of the form:
 | |
| #
 | |
| #       case OP_aaaa:      /* same as TK_bbbbb */
 | |
| #
 | |
| # The TK_ comment is optional.  If it is present, then the value assigned to
 | |
| # the OP_ is the same as the TK_ value.  If missing, the OP_ value is assigned
 | |
| # a small integer that is different from every other OP_ value.
 | |
| #
 | |
| # We go to the trouble of making some OP_ values the same as TK_ values
 | |
| # as an optimization.  During parsing, things like expression operators
 | |
| # are coded with TK_ values such as TK_ADD, TK_DIVIDE, and so forth.  Later
 | |
| # during code generation, we need to generate corresponding opcodes like
 | |
| # OP_Add and OP_Divide.  By making TK_ADD==OP_Add and TK_DIVIDE==OP_Divide,
 | |
| # code to translate from one to the other is avoided.  This makes the
 | |
| # code generator smaller and faster.
 | |
| #
 | |
| # This script also scans for lines of the form:
 | |
| #
 | |
| #       case OP_aaaa:       /* jump, in1, in2, in3, out2-prerelease, out3 */
 | |
| #
 | |
| # When such comments are found on an opcode, it means that certain
 | |
| # properties apply to that opcode.  Set corresponding flags using the
 | |
| # OPFLG_INITIALIZER macro.
 | |
| #
 | |
| 
 | |
| set in stdin
 | |
| set currentOp {}
 | |
| set nOp 0
 | |
| while {![eof $in]} {
 | |
|   set line [gets $in]
 | |
| 
 | |
|   # Remember the TK_ values from the parse.h file. 
 | |
|   # NB:  The "TK_" prefix stands for "ToKen", not the graphical Tk toolkit
 | |
|   # commonly associated with TCL.
 | |
|   #
 | |
|   if {[regexp {^#define TK_} $line]} {
 | |
|     set tk([lindex $line 1]) [lindex $line 2]
 | |
|     continue
 | |
|   }
 | |
| 
 | |
|   # Find "/* Opcode: " lines in the vdbe.c file.  Each one introduces
 | |
|   # a new opcode.  Remember which parameters are used.
 | |
|   #
 | |
|   if {[regexp {^.. Opcode: } $line]} {
 | |
|     set currentOp OP_[lindex $line 2]
 | |
|     set m 0
 | |
|     foreach term $line {
 | |
|       switch $term {
 | |
|         P1 {incr m 1}
 | |
|         P2 {incr m 2}
 | |
|         P3 {incr m 4}
 | |
|         P4 {incr m 8}
 | |
|         P5 {incr m 16}
 | |
|       }
 | |
|     }
 | |
|     set paramused($currentOp) $m
 | |
|   }
 | |
| 
 | |
|   # Find "** Synopsis: " lines that follow Opcode:
 | |
|   #
 | |
|   if {[regexp {^.. Synopsis: (.*)} $line all x] && $currentOp!=""} {
 | |
|     set synopsis($currentOp) [string trim $x]
 | |
|   }
 | |
| 
 | |
|   # Scan for "case OP_aaaa:" lines in the vdbe.c file
 | |
|   #
 | |
|   if {[regexp {^case OP_} $line]} {
 | |
|     set line [split $line]
 | |
|     set name [string trim [lindex $line 1] :]
 | |
|     set op($name) -1
 | |
|     set jump($name) 0
 | |
|     set in1($name) 0
 | |
|     set in2($name) 0
 | |
|     set in3($name) 0
 | |
|     set out2($name) 0
 | |
|     set out3($name) 0
 | |
|     for {set i 3} {$i<[llength $line]-1} {incr i} {
 | |
|        switch [string trim [lindex $line $i] ,] {
 | |
|          same {
 | |
|            incr i
 | |
|            if {[lindex $line $i]=="as"} {
 | |
|              incr i
 | |
|              set sym [string trim [lindex $line $i] ,]
 | |
|              set val $tk($sym)
 | |
|              set op($name) $val
 | |
|              set used($val) 1
 | |
|              set sameas($val) $sym
 | |
|              set def($val) $name
 | |
|            }
 | |
|          }
 | |
|          jump {set jump($name) 1}
 | |
|          in1  {set in1($name) 1}
 | |
|          in2  {set in2($name) 1}
 | |
|          in3  {set in3($name) 1}
 | |
|          out2 {set out2($name) 1}
 | |
|          out3 {set out3($name) 1}
 | |
|        }
 | |
|     }
 | |
|     set order($nOp) $name
 | |
|     incr nOp
 | |
|   }
 | |
| }
 | |
| 
 | |
| # Assign numbers to all opcodes and output the result.
 | |
| #
 | |
| puts "/* Automatically generated.  Do not edit */"
 | |
| puts "/* See the tool/mkopcodeh.tcl script for details */"
 | |
| foreach name {OP_Noop OP_Explain} {
 | |
|   set jump($name) 0
 | |
|   set in1($name) 0
 | |
|   set in2($name) 0
 | |
|   set in3($name) 0
 | |
|   set out2($name) 0
 | |
|   set out3($name) 0
 | |
|   set op($name) -1
 | |
|   set order($nOp) $name
 | |
|   incr nOp
 | |
| }
 | |
| 
 | |
| # The following are the opcodes that are processed by resolveP2Values()
 | |
| #
 | |
| set rp2v_ops {
 | |
|   OP_Transaction
 | |
|   OP_AutoCommit
 | |
|   OP_Savepoint
 | |
|   OP_Checkpoint
 | |
|   OP_Vacuum
 | |
|   OP_JournalMode
 | |
|   OP_VUpdate
 | |
|   OP_VFilter
 | |
|   OP_Next
 | |
|   OP_NextIfOpen
 | |
|   OP_SorterNext
 | |
|   OP_Prev
 | |
|   OP_PrevIfOpen
 | |
| }
 | |
| 
 | |
| # Assign small values to opcodes that are processed by resolveP2Values()
 | |
| # to make code generation for the switch() statement smaller and faster.
 | |
| #
 | |
| set cnt -1
 | |
| for {set i 0} {$i<$nOp} {incr i} {
 | |
|   set name $order($i)
 | |
|   if {[lsearch $rp2v_ops $name]>=0} {
 | |
|     incr cnt
 | |
|     while {[info exists used($cnt)]} {incr cnt}
 | |
|     set op($name) $cnt
 | |
|     set used($cnt) 1
 | |
|     set def($cnt) $name
 | |
|   }
 | |
| }
 | |
| 
 | |
| # Assign the next group of values to JUMP opcodes
 | |
| #
 | |
| for {set i 0} {$i<$nOp} {incr i} {
 | |
|   set name $order($i)
 | |
|   if {$op($name)>=0} continue
 | |
|   if {!$jump($name)} continue
 | |
|   incr cnt
 | |
|   while {[info exists used($cnt)]} {incr cnt}
 | |
|   set op($name) $cnt
 | |
|   set used($cnt) 1
 | |
|   set def($cnt) $name
 | |
| }
 | |
| 
 | |
| # Find the numeric value for the largest JUMP opcode
 | |
| #
 | |
| set mxJump -1
 | |
| for {set i 0} {$i<$nOp} {incr i} {
 | |
|   set name $order($i)
 | |
|   if {$jump($name) && $op($name)>$mxJump} {set mxJump $op($name)}
 | |
| }
 | |
| 
 | |
| 
 | |
| # Generate the numeric values for all remaining opcodes
 | |
| #
 | |
| for {set i 0} {$i<$nOp} {incr i} {
 | |
|   set name $order($i)
 | |
|   if {$op($name)<0} {
 | |
|     incr cnt
 | |
|     while {[info exists used($cnt)]} {incr cnt}
 | |
|     set op($name) $cnt
 | |
|     set used($cnt) 1
 | |
|     set def($cnt) $name
 | |
|   }
 | |
| }
 | |
| 
 | |
| set max [lindex [lsort -decr -integer [array names used]] 0]
 | |
| for {set i 0} {$i<=$max} {incr i} {
 | |
|   if {![info exists used($i)]} {
 | |
|     set def($i) "OP_NotUsed_$i"
 | |
|   }
 | |
|   if {$i>$max} {set max $i}
 | |
|   set name $def($i)
 | |
|   puts -nonewline [format {#define %-16s %3d} $name $i]
 | |
|   set com {}
 | |
|   if {[info exists sameas($i)]} {
 | |
|     set com "same as $sameas($i)"
 | |
|   }
 | |
|   if {[info exists synopsis($name)]} {
 | |
|     set x $synopsis($name)
 | |
|     if {$com==""} {
 | |
|       set com "synopsis: $x"
 | |
|     } else {
 | |
|       append com ", synopsis: $x"
 | |
|     }
 | |
|   }
 | |
|   if {$com!=""} {
 | |
|     puts -nonewline [format " /* %-42s */" $com]
 | |
|   }
 | |
|   puts ""
 | |
| }
 | |
| 
 | |
| if {$max>255} {
 | |
|   error "More than 255 opcodes - VdbeOp.opcode is of type u8!"
 | |
| }
 | |
| 
 | |
| # Generate the bitvectors:
 | |
| #
 | |
| set bv(0) 0
 | |
| for {set i 0} {$i<=$max} {incr i} {
 | |
|   set x 0
 | |
|   set name $def($i)
 | |
|   if {[string match OP_NotUsed* $name]==0} {
 | |
|     if {$jump($name)}  {incr x 1}
 | |
|     if {$in1($name)}   {incr x 2}
 | |
|     if {$in2($name)}   {incr x 4}
 | |
|     if {$in3($name)}   {incr x 8}
 | |
|     if {$out2($name)}  {incr x 16}
 | |
|     if {$out3($name)}  {incr x 32}
 | |
|   }
 | |
|   set bv($i) $x
 | |
| }
 | |
| puts ""
 | |
| puts "/* Properties such as \"out2\" or \"jump\" that are specified in"
 | |
| puts "** comments following the \"case\" for each opcode in the vdbe.c"
 | |
| puts "** are encoded into bitvectors as follows:"
 | |
| puts "*/"
 | |
| puts "#define OPFLG_JUMP        0x01  /* jump:  P2 holds jmp target */"
 | |
| puts "#define OPFLG_IN1         0x02  /* in1:   P1 is an input */"
 | |
| puts "#define OPFLG_IN2         0x04  /* in2:   P2 is an input */"
 | |
| puts "#define OPFLG_IN3         0x08  /* in3:   P3 is an input */"
 | |
| puts "#define OPFLG_OUT2        0x10  /* out2:  P2 is an output */"
 | |
| puts "#define OPFLG_OUT3        0x20  /* out3:  P3 is an output */"
 | |
| puts "#define OPFLG_INITIALIZER \173\\"
 | |
| for {set i 0} {$i<=$max} {incr i} {
 | |
|   if {$i%8==0} {
 | |
|     puts -nonewline [format "/* %3d */" $i]
 | |
|   }
 | |
|   puts -nonewline [format " 0x%02x," $bv($i)]
 | |
|   if {$i%8==7} {
 | |
|     puts "\\"
 | |
|   }
 | |
| }
 | |
| puts "\175"
 | |
| puts ""
 | |
| puts "/* The sqlite3P2Values() routine is able to run faster if it knows"
 | |
| puts "** the value of the largest JUMP opcode.  The smaller the maximum"
 | |
| puts "** JUMP opcode the better, so the mkopcodeh.tcl script that"
 | |
| puts "** generated this include file strives to group all JUMP opcodes"
 | |
| puts "** together near the beginning of the list."
 | |
| puts "*/"
 | |
| puts "#define SQLITE_MX_JUMP_OPCODE  $mxJump  /* Maximum JUMP opcode */"
 |