1 /*
2 Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is also distributed with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have included with MySQL.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License, version 2.0, for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25 #ifndef NDB_INTERPRETER_HPP
26 #define NDB_INTERPRETER_HPP
27
28 #include <ndb_types.h>
29
30 #define JAM_FILE_ID 215
31
32
33 class Interpreter {
34 public:
35
mod4(Uint32 len)36 inline static Uint32 mod4(Uint32 len){
37 return len + ((4 - (len & 3)) & 3);
38 }
39
40
41 /**
42 * General Mnemonic format
43 *
44 * i = Instruction - 5 Bits ( 0 - 5 ) max 63
45 * x = Register 1 - 3 Bits ( 6 - 8 ) max 7
46 * y = Register 2 - 3 Bits ( 9 -11 ) max 7
47 * b = Branch offset (only branches)
48 *
49 * 1111111111222222222233
50 * 01234567890123456789012345678901
51 * iiiiiixxxyyy bbbbbbbbbbbbbbbb
52 *
53 *
54 */
55
56 /**
57 * Instructions
58 */
59 STATIC_CONST( READ_ATTR_INTO_REG = 1 );
60 STATIC_CONST( WRITE_ATTR_FROM_REG = 2 );
61 STATIC_CONST( LOAD_CONST_NULL = 3 );
62 STATIC_CONST( LOAD_CONST16 = 4 );
63 STATIC_CONST( LOAD_CONST32 = 5 );
64 STATIC_CONST( LOAD_CONST64 = 6 );
65 STATIC_CONST( ADD_REG_REG = 7 );
66 STATIC_CONST( SUB_REG_REG = 8 );
67 STATIC_CONST( BRANCH = 9 );
68 STATIC_CONST( BRANCH_REG_EQ_NULL = 10 );
69 STATIC_CONST( BRANCH_REG_NE_NULL = 11 );
70 STATIC_CONST( BRANCH_EQ_REG_REG = 12 );
71 STATIC_CONST( BRANCH_NE_REG_REG = 13 );
72 STATIC_CONST( BRANCH_LT_REG_REG = 14 );
73 STATIC_CONST( BRANCH_LE_REG_REG = 15 );
74 STATIC_CONST( BRANCH_GT_REG_REG = 16 );
75 STATIC_CONST( BRANCH_GE_REG_REG = 17 );
76 STATIC_CONST( EXIT_OK = 18 );
77 STATIC_CONST( EXIT_REFUSE = 19 );
78 STATIC_CONST( CALL = 20 );
79 STATIC_CONST( RETURN = 21 );
80 STATIC_CONST( EXIT_OK_LAST = 22 );
81 STATIC_CONST( BRANCH_ATTR_OP_ARG = 23 );
82 STATIC_CONST( BRANCH_ATTR_EQ_NULL = 24 );
83 STATIC_CONST( BRANCH_ATTR_NE_NULL = 25 );
84 STATIC_CONST( BRANCH_ATTR_OP_ARG_2 = 26 );
85 STATIC_CONST( BRANCH_ATTR_OP_ATTR = 27 );
86
87 /**
88 * Macros for creating code
89 */
90 static Uint32 Read(Uint32 AttrId, Uint32 Register);
91 static Uint32 Write(Uint32 AttrId, Uint32 Register);
92
93 static Uint32 LoadNull(Uint32 Register);
94 static Uint32 LoadConst16(Uint32 Register, Uint32 Value);
95 static Uint32 LoadConst32(Uint32 Register); // Value in next word
96 static Uint32 LoadConst64(Uint32 Register); // Value in next 2 words
97 static Uint32 Add(Uint32 DstReg, Uint32 SrcReg1, Uint32 SrcReg2);
98 static Uint32 Sub(Uint32 DstReg, Uint32 SrcReg1, Uint32 SrcReg2);
99 static Uint32 Branch(Uint32 Inst, Uint32 Reg1, Uint32 Reg2);
100 static Uint32 ExitOK();
101 static Uint32 ExitLastOK();
102
103 /**
104 * Branch OP_ARG (Attr1 <op> <value arg>)
105 *
106 * i = Instruction - 5 Bits ( 0 - 5 ) max 63
107 * a = Attribute id - 16 bits
108 * l = Length of string (bytes) - 16 bits OP_ARG
109 * p = parameter no - 16 bits OP_ARG_2
110 * b = Branch offset (words) - 16 bits
111 * t = branch type - 4 bits
112 * d = Array length diff
113 * v = Varchar flag
114 *
115 * 1111111111222222222233
116 * 01234567890123456789012345678901
117 * iiiiii ddvttttbbbbbbbbbbbbbbbb
118 * aaaaaaaaaaaaaaaallllllllllllllll
119 * -string.... -
120 *
121 *
122 * Branch OP_ARG_2 (Attr1 <op> <ParamNo>)
123 *
124 * i = Instruction - 5 Bits ( 0 - 5 ) max 63
125 * a = Attribute id - 16 bits
126 * p = parameter no - 16 bits OP_ARG_2
127 * b = Branch offset (words) - 16 bits
128 * t = branch type - 4 bits
129 *
130 * 1111111111222222222233
131 * 01234567890123456789012345678901
132 * iiiiii ttttbbbbbbbbbbbbbbbb
133 * aaaaaaaaaaaaaaaapppppppppppppppp
134 *
135 *
136 * Branch OP_ATTR (Attr1 <op> Attr2)
137 *
138 * i = Instruction - 5 Bits ( 0 - 5 ) max 63
139 * a = Attribute id1 - 16 bits
140 * A = Attribute id2 - 16 bits
141 * b = Branch offset (words) - 16 bits
142 * t = branch type - 4 bits
143 *
144 * 1111111111222222222233
145 * 01234567890123456789012345678901
146 * iiiiii ttttbbbbbbbbbbbbbbbb
147 * aaaaaaaaaaaaaaaaAAAAAAAAAAAAAAAA
148 */
149
150 enum UnaryCondition {
151 IS_NULL = 0,
152 IS_NOT_NULL = 1
153 };
154
155 enum BinaryCondition {
156 EQ = 0,
157 NE = 1,
158 LT = 2,
159 LE = 3,
160 GT = 4,
161 GE = 5,
162 LIKE = 6,
163 NOT_LIKE = 7,
164 AND_EQ_MASK = 8,
165 AND_NE_MASK = 9,
166 AND_EQ_ZERO = 10,
167 AND_NE_ZERO = 11
168 };
169 // Compare Attr with literal
170 // TODO : Remove other 2 unused parameters.
171 static Uint32 BranchCol(BinaryCondition cond,
172 Uint32 arrayLengthDiff, Uint32 varchar);
173 static Uint32 BranchCol_2(Uint32 AttrId);
174 static Uint32 BranchCol_2(Uint32 AttrId, Uint32 Len);
175
176 // Compare Attr with parameter
177 static Uint32 BranchColParameter(BinaryCondition cond);
178 static Uint32 BranchColParameter_2(Uint32 AttrId, Uint32 ParamNo);
179
180 // Compare two Attr from same table
181 static Uint32 BranchColAttrId(BinaryCondition cond);
182 static Uint32 BranchColAttrId_2(Uint32 AttrId1, Uint32 AttrId2);
183
184 static Uint32 getBinaryCondition(Uint32 op1);
185 static Uint32 getArrayLengthDiff(Uint32 op1);
186 static Uint32 isVarchar(Uint32 op1);
187 static Uint32 getBranchCol_AttrId(Uint32 op2);
188 static Uint32 getBranchCol_AttrId2(Uint32 op2);
189 static Uint32 getBranchCol_Len(Uint32 op2);
190 static Uint32 getBranchCol_ParamNo(Uint32 op2);
191
192 /**
193 * Macros for decoding code
194 */
195 static Uint32 getOpCode(Uint32 op);
196 static Uint32 getReg1(Uint32 op);
197 static Uint32 getReg2(Uint32 op);
198 static Uint32 getReg3(Uint32 op);
199 static Uint32 getLabel(Uint32 op);
200
201 /**
202 * Instruction pre-processing required.
203 */
204 enum InstructionPreProcessing
205 {
206 NONE,
207 LABEL_ADDRESS_REPLACEMENT,
208 SUB_ADDRESS_REPLACEMENT
209 };
210
211 /* This method is used to determine what sort of
212 * instruction processing is required, and the address
213 * of the next instruction in the stream
214 */
215 static Uint32 *getInstructionPreProcessingInfo(Uint32 *op,
216 InstructionPreProcessing& processing);
217 };
218
219 inline
220 Uint32
Read(Uint32 AttrId,Uint32 Register)221 Interpreter::Read(Uint32 AttrId, Uint32 Register){
222 return (AttrId << 16) + (Register << 6) + READ_ATTR_INTO_REG;
223 }
224
225 inline
226 Uint32
Write(Uint32 AttrId,Uint32 Register)227 Interpreter::Write(Uint32 AttrId, Uint32 Register){
228 return (AttrId << 16) + (Register << 6) + WRITE_ATTR_FROM_REG;
229 }
230
231 inline
232 Uint32
LoadNull(Uint32 Register)233 Interpreter::LoadNull(Uint32 Register){
234 return (Register << 6) + LOAD_CONST_NULL;
235 }
236
237 inline
238 Uint32
LoadConst16(Uint32 Register,Uint32 Value)239 Interpreter::LoadConst16(Uint32 Register, Uint32 Value){
240 return (Value << 16) + (Register << 6) + LOAD_CONST16;
241 }
242
243 inline
244 Uint32
LoadConst32(Uint32 Register)245 Interpreter::LoadConst32(Uint32 Register){
246 return (Register << 6) + LOAD_CONST32;
247 }
248
249 inline
250 Uint32
LoadConst64(Uint32 Register)251 Interpreter::LoadConst64(Uint32 Register){
252 return (Register << 6) + LOAD_CONST64;
253 }
254
255 inline
256 Uint32
Add(Uint32 Dcoleg,Uint32 SrcReg1,Uint32 SrcReg2)257 Interpreter::Add(Uint32 Dcoleg, Uint32 SrcReg1, Uint32 SrcReg2){
258 return (SrcReg1 << 6) + (SrcReg2 << 9) + (Dcoleg << 16) + ADD_REG_REG;
259 }
260
261 inline
262 Uint32
Sub(Uint32 Dcoleg,Uint32 SrcReg1,Uint32 SrcReg2)263 Interpreter::Sub(Uint32 Dcoleg, Uint32 SrcReg1, Uint32 SrcReg2){
264 return (SrcReg1 << 6) + (SrcReg2 << 9) + (Dcoleg << 16) + SUB_REG_REG;
265 }
266
267 inline
268 Uint32
Branch(Uint32 Inst,Uint32 Reg1,Uint32 Reg2)269 Interpreter::Branch(Uint32 Inst, Uint32 Reg1, Uint32 Reg2){
270 return (Reg1 << 9) + (Reg2 << 6) + Inst;
271 }
272
273 inline
274 Uint32
BranchColAttrId(BinaryCondition cond)275 Interpreter::BranchColAttrId(BinaryCondition cond) {
276 return
277 BRANCH_ATTR_OP_ATTR + // Compare two ATTRs
278 (cond << 12);
279 }
280
281 inline
282 Uint32
BranchColAttrId_2(Uint32 AttrId1,Uint32 AttrId2)283 Interpreter::BranchColAttrId_2(Uint32 AttrId1, Uint32 AttrId2) {
284 return (AttrId1 << 16) + AttrId2;
285 }
286
287 inline
288 Uint32
BranchCol(BinaryCondition cond,Uint32 arrayLengthDiff,Uint32 varchar)289 Interpreter::BranchCol(BinaryCondition cond,
290 Uint32 arrayLengthDiff,
291 Uint32 varchar){
292 //ndbout_c("BranchCol: cond=%d diff=%u varchar=%u",
293 //cond, arrayLengthDiff, varchar);
294 return
295 BRANCH_ATTR_OP_ARG +
296 (arrayLengthDiff << 9) +
297 (varchar << 11) +
298 (cond << 12);
299 }
300
301 inline
302 Uint32
BranchColParameter(BinaryCondition cond)303 Interpreter::BranchColParameter(BinaryCondition cond)
304 {
305 return BRANCH_ATTR_OP_ARG_2 + (cond << 12);
306 }
307
308 inline
309 Uint32
BranchColParameter_2(Uint32 AttrId,Uint32 ParamNo)310 Interpreter::BranchColParameter_2(Uint32 AttrId, Uint32 ParamNo){
311 return (AttrId << 16) + ParamNo;
312 }
313
314 inline
315 Uint32
BranchCol_2(Uint32 AttrId,Uint32 Len)316 Interpreter::BranchCol_2(Uint32 AttrId, Uint32 Len){
317 return (AttrId << 16) + Len;
318 }
319
320 inline
321 Uint32
BranchCol_2(Uint32 AttrId)322 Interpreter::BranchCol_2(Uint32 AttrId){
323 return (AttrId << 16);
324 }
325
326 inline
327 Uint32
getBinaryCondition(Uint32 op)328 Interpreter::getBinaryCondition(Uint32 op){
329 return (op >> 12) & 0xf;
330 }
331
332 inline
333 Uint32
getArrayLengthDiff(Uint32 op)334 Interpreter::getArrayLengthDiff(Uint32 op){
335 return (op >> 9) & 0x3;
336 }
337
338 inline
339 Uint32
isVarchar(Uint32 op)340 Interpreter::isVarchar(Uint32 op){
341 return (op >> 11) & 1;
342 }
343
344 inline
345 Uint32
getBranchCol_AttrId(Uint32 op)346 Interpreter::getBranchCol_AttrId(Uint32 op){
347 return (op >> 16) & 0xFFFF;
348 }
349
350 inline
351 Uint32
getBranchCol_AttrId2(Uint32 op)352 Interpreter::getBranchCol_AttrId2(Uint32 op){
353 return op & 0xFFFF;
354 }
355
356 inline
357 Uint32
getBranchCol_Len(Uint32 op)358 Interpreter::getBranchCol_Len(Uint32 op){
359 return op & 0xFFFF;
360 }
361
362 inline
363 Uint32
getBranchCol_ParamNo(Uint32 op)364 Interpreter::getBranchCol_ParamNo(Uint32 op){
365 return op & 0xFFFF;
366 }
367
368 inline
369 Uint32
ExitOK()370 Interpreter::ExitOK(){
371 return EXIT_OK;
372 }
373
374 inline
375 Uint32
ExitLastOK()376 Interpreter::ExitLastOK(){
377 return EXIT_OK_LAST;
378 }
379
380 inline
381 Uint32
getOpCode(Uint32 op)382 Interpreter::getOpCode(Uint32 op){
383 return op & 0x3f;
384 }
385
386 inline
387 Uint32
getReg1(Uint32 op)388 Interpreter::getReg1(Uint32 op){
389 return (op >> 6) & 0x7;
390 }
391
392 inline
393 Uint32
getReg2(Uint32 op)394 Interpreter::getReg2(Uint32 op){
395 return (op >> 9) & 0x7;
396 }
397
398 inline
399 Uint32
getReg3(Uint32 op)400 Interpreter::getReg3(Uint32 op){
401 return (op >> 16) & 0x7;
402 }
403
404 inline
405 Uint32
getLabel(Uint32 op)406 Interpreter::getLabel(Uint32 op){
407 return (op >> 16) & 0xffff;
408 }
409
410 inline
411 Uint32*
getInstructionPreProcessingInfo(Uint32 * op,InstructionPreProcessing & processing)412 Interpreter::getInstructionPreProcessingInfo(Uint32 *op,
413 InstructionPreProcessing& processing )
414 {
415 /* Given an instruction, get a pointer to the
416 * next instruction in the stream.
417 * Returns NULL on error.
418 */
419 processing= NONE;
420 Uint32 opCode= getOpCode(*op);
421
422 switch( opCode )
423 {
424 case READ_ATTR_INTO_REG:
425 case WRITE_ATTR_FROM_REG:
426 case LOAD_CONST_NULL:
427 case LOAD_CONST16:
428 return op + 1;
429 case LOAD_CONST32:
430 return op + 2;
431 case LOAD_CONST64:
432 return op + 3;
433 case ADD_REG_REG:
434 case SUB_REG_REG:
435 return op + 1;
436 case BRANCH:
437 case BRANCH_REG_EQ_NULL:
438 case BRANCH_REG_NE_NULL:
439 case BRANCH_EQ_REG_REG:
440 case BRANCH_NE_REG_REG:
441 case BRANCH_LT_REG_REG:
442 case BRANCH_LE_REG_REG:
443 case BRANCH_GT_REG_REG:
444 case BRANCH_GE_REG_REG:
445 processing= LABEL_ADDRESS_REPLACEMENT;
446 return op + 1;
447 case BRANCH_ATTR_OP_ARG:
448 {
449 /* We need to take the length from the second word of the
450 * branch instruction so we can skip over the inline const
451 * comparison data.
452 */
453 processing= LABEL_ADDRESS_REPLACEMENT;
454 Uint32 byteLength= getBranchCol_Len(*(op+1));
455 Uint32 wordLength= (byteLength + 3) >> 2;
456 return op + 2 + wordLength;
457 }
458 case BRANCH_ATTR_OP_ARG_2:
459 case BRANCH_ATTR_OP_ATTR:
460 {
461 /* Second word of the branch instruction refer either paramNo
462 * or attrId to be compared -> fixed length.
463 */
464 processing= LABEL_ADDRESS_REPLACEMENT;
465 return op + 2;
466 }
467 case BRANCH_ATTR_EQ_NULL:
468 case BRANCH_ATTR_NE_NULL:
469 processing= LABEL_ADDRESS_REPLACEMENT;
470 return op + 2;
471 case EXIT_OK:
472 case EXIT_OK_LAST:
473 case EXIT_REFUSE:
474 return op + 1;
475 case CALL:
476 processing= SUB_ADDRESS_REPLACEMENT;
477 return op + 1;
478 case RETURN:
479 return op + 1;
480
481 default:
482 return NULL;
483 }
484 }
485
486
487 #undef JAM_FILE_ID
488
489 #endif
490