SQLite

Check-in [6ee2950b27]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Keep generated opcode values grouped together when required, even when they do not correspond to a token.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 6ee2950b272ede475e485bfaa7d413eaa81482fe9dd6452aeeaf95ff7938f7da
User & Date: mistachkin 2018-07-25 15:12:29.938
Context
2018-07-25
15:25
Fix a buffer overread in fts5. (check-in: 0e3de8abbb user: dan tags: trunk)
15:12
Keep generated opcode values grouped together when required, even when they do not correspond to a token. (check-in: 6ee2950b27 user: mistachkin tags: trunk)
07:29
Fix a typo in the documentation for sqlite3_snapshot_get(). (check-in: cd9713c9a8 user: dan tags: trunk)
Changes
Side-by-Side Diff Ignore Whitespace Patch
Changes to src/vdbe.c.
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898




3899
3900
3901
3902
3903
3904
3905
3888
3889
3890
3891
3892
3893
3894




3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905







-
-
-
-
+
+
+
+







** else jump immediately to P2.  When the cursor is OPFLAG_SEEKEQ, this
** opcode must be followed by an IdxGE opcode with the same arguments.
** The IdxGE opcode will be skipped if this opcode succeeds, but the
** IdxGE opcode will be used on subsequent loop iterations.
**
** See also: Found, NotFound, SeekGt, SeekGe, SeekLt
*/
case OP_SeekLT:         /* jump, in3 */
case OP_SeekLE:         /* jump, in3 */
case OP_SeekGE:         /* jump, in3 */
case OP_SeekGT: {       /* jump, in3 */
case OP_SeekLT:         /* jump, in3, group */
case OP_SeekLE:         /* jump, in3, group */
case OP_SeekGE:         /* jump, in3, group */
case OP_SeekGT: {       /* jump, in3, group */
  int res;           /* Comparison result */
  int oc;            /* Opcode */
  VdbeCursor *pC;    /* The cursor to seek */
  UnpackedRecord r;  /* The key to seek for */
  int nField;        /* Number of columns or fields in the key */
  i64 iKey;          /* The rowid we are to seek to */
  int eqOnly;        /* Only interested in == results */
7215
7216
7217
7218
7219
7220
7221
7222
7223


7224
7225
7226
7227
7228
7229
7230
7215
7216
7217
7218
7219
7220
7221


7222
7223
7224
7225
7226
7227
7228
7229
7230







-
-
+
+







** automatically converted into an sqlite3_context object and the operation
** changed to this OP_Function opcode.  In this way, the initialization of
** the sqlite3_context object occurs only once, rather than once for each
** evaluation of the function.
**
** See also: Function0, AggStep, AggFinal
*/
case OP_PureFunc0:
case OP_Function0: {
case OP_PureFunc0:              /* group */
case OP_Function0: {            /* group */
  int n;
  sqlite3_context *pCtx;

  assert( pOp->p4type==P4_FUNCDEF );
  n = pOp->p5;
  assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
  assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem+1 - p->nCursor)+1) );
7240
7241
7242
7243
7244
7245
7246
7247
7248


7249
7250
7251
7252
7253
7254
7255
7240
7241
7242
7243
7244
7245
7246


7247
7248
7249
7250
7251
7252
7253
7254
7255







-
-
+
+







  pOp->p4type = P4_FUNCCTX;
  pOp->p4.pCtx = pCtx;
  assert( OP_PureFunc == OP_PureFunc0+2 );
  assert( OP_Function == OP_Function0+2 );
  pOp->opcode += 2;
  /* Fall through into OP_Function */
}
case OP_PureFunc:
case OP_Function: {
case OP_PureFunc:              /* group */
case OP_Function: {            /* group */
  int i;
  sqlite3_context *pCtx;

  assert( pOp->p4type==P4_FUNCCTX );
  pCtx = pOp->p4.pCtx;

  /* If this function is inside of a trigger, the register array in aMem[]
Changes to tool/mkopcodeh.tcl.
20
21
22
23
24
25
26
27

28
29
30
31
32
33
34
35

36

37
38
39
40
41
42
43
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







-
+








+

+







# 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 */
#       case OP_aaaa:       /* jump, in1, in2, in3, out2, 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 prevName {}
set nOp 0
set nGroup 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.
  #
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
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







+




















+
-
-
-
-
-
-
+
+
+
+
+
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+

+







  # 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] :]
    if {$name=="OP_Abortable"} continue;  # put OP_Abortable last 
    set op($name) -1
    set group($name) 0
    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
           }
         }
         group {set group($name) 1}
         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}
         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}
       }
    }
    if {$group($name)} {
      set newGroup 0
      if {[info exists groups($nGroup)]} {
        if {$prevName=="" || !$group($prevName)} {
          set newGroup 1
        }
      }
      lappend groups($nGroup) $name
      if {$newGroup} {incr nGroup}
    } else {
      if {$prevName!="" && $group($prevName)} {
        incr nGroup
      }
    }
    set order($nOp) $name
    set prevName $name
    incr nOp
  }
}

# Assign numbers to all opcodes and output the result.
#
puts "/* Automatically generated.  Do not edit */"
177
178
179
180
181
182
183
184



185





























186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206

207
208
209
210
211
212
213
196
197
198
199
200
201
202

203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255

256
257
258
259
260
261
262
263







-
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




















-
+







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
# Generate the numeric values for all remaining opcodes, while
# preserving any groupings of opcodes (i.e. those that must be
# together).
#
for {set g 0} {$g<$nGroup} {incr g} {
  set gLen [llength $groups($g)]
  set ok 0; set start -1
  while {!$ok} {
    set seek $cnt; incr seek
    while {[info exists used($seek)]} {incr seek}
    set ok 1; set start $seek
    for {set j 0} {$j<$gLen} {incr j} {
      incr seek
      if {[info exists used($seek)]} {
        set ok 0; break
      }
    }
  }
  if {$ok} {
    set next $start
    for {set j 0} {$j<$gLen} {incr j} {
      set name [lindex $groups($g) $j]
      if {$op($name)>=0} continue
      set op($name) $next
      set used($next) 1
      set def($next) $name
      incr next
    }
  } else {
    error "cannot find opcodes for group: $groups($g)"
  }
}

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 {$jump($name)} {
  if {[info exists jump($name)] && $jump($name)} {
    lappend com "jump"
  }
  if {[info exists sameas($i)]} {
    lappend com "same as $sameas($i)"
  }
  if {[info exists synopsis($name)]} {
    lappend com "synopsis: $synopsis($name)"