1 /*
2 Copyright (c) 2003, 2021, Oracle and/or its affiliates.
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
86 /**
87 * Macros for creating code
88 */
89 static Uint32 Read(Uint32 AttrId, Uint32 Register);
90 static Uint32 Write(Uint32 AttrId, Uint32 Register);
91
92 static Uint32 LoadNull(Uint32 Register);
93 static Uint32 LoadConst16(Uint32 Register, Uint32 Value);
94 static Uint32 LoadConst32(Uint32 Register); // Value in next word
95 static Uint32 LoadConst64(Uint32 Register); // Value in next 2 words
96 static Uint32 Add(Uint32 DstReg, Uint32 SrcReg1, Uint32 SrcReg2);
97 static Uint32 Sub(Uint32 DstReg, Uint32 SrcReg1, Uint32 SrcReg2);
98 static Uint32 Branch(Uint32 Inst, Uint32 Reg1, Uint32 Reg2);
99 static Uint32 ExitOK();
100 static Uint32 ExitLastOK();
101
102 /**
103 * Branch OP_ARG
104 *
105 * i = Instruction - 5 Bits ( 0 - 5 ) max 63
106 * a = Attribute id - 16 bits
107 * l = Length of string (bytes) - 16 bits OP_ARG
108 * p = parameter no - 16 bits OP_ARG_2
109 * b = Branch offset (words) - 16 bits
110 * t = branch type - 4 bits
111 * d = Array length diff
112 * v = Varchar flag
113 *
114 * 1111111111222222222233
115 * 01234567890123456789012345678901
116 * iiiiii ddvttttbbbbbbbbbbbbbbbb
117 * aaaaaaaaaaaaaaaallllllllllllllll
118 * -string.... -
119 */
120 enum UnaryCondition {
121 IS_NULL = 0,
122 IS_NOT_NULL = 1
123 };
124
125 enum BinaryCondition {
126 EQ = 0,
127 NE = 1,
128 LT = 2,
129 LE = 3,
130 GT = 4,
131 GE = 5,
132 LIKE = 6,
133 NOT_LIKE = 7,
134 AND_EQ_MASK = 8,
135 AND_NE_MASK = 9,
136 AND_EQ_ZERO = 10,
137 AND_NE_ZERO = 11
138 };
139 // TODO : Remove other 2 unused parameters.
140 static Uint32 BranchCol(BinaryCondition cond,
141 Uint32 arrayLengthDiff, Uint32 varchar);
142 static Uint32 BranchCol_2(Uint32 AttrId);
143 static Uint32 BranchCol_2(Uint32 AttrId, Uint32 Len);
144
145 static Uint32 BranchColParameter(BinaryCondition cond);
146 static Uint32 BranchColParameter_2(Uint32 AttrId, Uint32 ParamNo);
147
148 static Uint32 getBinaryCondition(Uint32 op1);
149 static Uint32 getArrayLengthDiff(Uint32 op1);
150 static Uint32 isVarchar(Uint32 op1);
151 static Uint32 getBranchCol_AttrId(Uint32 op2);
152 static Uint32 getBranchCol_Len(Uint32 op2);
153 static Uint32 getBranchCol_ParamNo(Uint32 op2);
154
155 /**
156 * Macros for decoding code
157 */
158 static Uint32 getOpCode(Uint32 op);
159 static Uint32 getReg1(Uint32 op);
160 static Uint32 getReg2(Uint32 op);
161 static Uint32 getReg3(Uint32 op);
162 static Uint32 getLabel(Uint32 op);
163
164 /**
165 * Instruction pre-processing required.
166 */
167 enum InstructionPreProcessing
168 {
169 NONE,
170 LABEL_ADDRESS_REPLACEMENT,
171 SUB_ADDRESS_REPLACEMENT
172 };
173
174 /* This method is used to determine what sort of
175 * instruction processing is required, and the address
176 * of the next instruction in the stream
177 */
178 static Uint32 *getInstructionPreProcessingInfo(Uint32 *op,
179 InstructionPreProcessing& processing);
180 };
181
182 inline
183 Uint32
Read(Uint32 AttrId,Uint32 Register)184 Interpreter::Read(Uint32 AttrId, Uint32 Register){
185 return (AttrId << 16) + (Register << 6) + READ_ATTR_INTO_REG;
186 }
187
188 inline
189 Uint32
Write(Uint32 AttrId,Uint32 Register)190 Interpreter::Write(Uint32 AttrId, Uint32 Register){
191 return (AttrId << 16) + (Register << 6) + WRITE_ATTR_FROM_REG;
192 }
193
194 inline
195 Uint32
LoadNull(Uint32 Register)196 Interpreter::LoadNull(Uint32 Register){
197 return (Register << 6) + LOAD_CONST_NULL;
198 }
199
200 inline
201 Uint32
LoadConst16(Uint32 Register,Uint32 Value)202 Interpreter::LoadConst16(Uint32 Register, Uint32 Value){
203 return (Value << 16) + (Register << 6) + LOAD_CONST16;
204 }
205
206 inline
207 Uint32
LoadConst32(Uint32 Register)208 Interpreter::LoadConst32(Uint32 Register){
209 return (Register << 6) + LOAD_CONST32;
210 }
211
212 inline
213 Uint32
LoadConst64(Uint32 Register)214 Interpreter::LoadConst64(Uint32 Register){
215 return (Register << 6) + LOAD_CONST64;
216 }
217
218 inline
219 Uint32
Add(Uint32 Dcoleg,Uint32 SrcReg1,Uint32 SrcReg2)220 Interpreter::Add(Uint32 Dcoleg, Uint32 SrcReg1, Uint32 SrcReg2){
221 return (SrcReg1 << 6) + (SrcReg2 << 9) + (Dcoleg << 16) + ADD_REG_REG;
222 }
223
224 inline
225 Uint32
Sub(Uint32 Dcoleg,Uint32 SrcReg1,Uint32 SrcReg2)226 Interpreter::Sub(Uint32 Dcoleg, Uint32 SrcReg1, Uint32 SrcReg2){
227 return (SrcReg1 << 6) + (SrcReg2 << 9) + (Dcoleg << 16) + SUB_REG_REG;
228 }
229
230 inline
231 Uint32
Branch(Uint32 Inst,Uint32 Reg1,Uint32 Reg2)232 Interpreter::Branch(Uint32 Inst, Uint32 Reg1, Uint32 Reg2){
233 return (Reg1 << 9) + (Reg2 << 6) + Inst;
234 }
235
236 inline
237 Uint32
BranchCol(BinaryCondition cond,Uint32 arrayLengthDiff,Uint32 varchar)238 Interpreter::BranchCol(BinaryCondition cond,
239 Uint32 arrayLengthDiff,
240 Uint32 varchar){
241 //ndbout_c("BranchCol: cond=%d diff=%u varchar=%u",
242 //cond, arrayLengthDiff, varchar);
243 return
244 BRANCH_ATTR_OP_ARG +
245 (arrayLengthDiff << 9) +
246 (varchar << 11) +
247 (cond << 12);
248 }
249
250 inline
251 Uint32
BranchColParameter(BinaryCondition cond)252 Interpreter::BranchColParameter(BinaryCondition cond)
253 {
254 return BRANCH_ATTR_OP_ARG_2 + (cond << 12);
255 }
256
257 inline
258 Uint32
BranchColParameter_2(Uint32 AttrId,Uint32 ParamNo)259 Interpreter::BranchColParameter_2(Uint32 AttrId, Uint32 ParamNo){
260 return (AttrId << 16) + ParamNo;
261 }
262
263 inline
264 Uint32
BranchCol_2(Uint32 AttrId,Uint32 Len)265 Interpreter::BranchCol_2(Uint32 AttrId, Uint32 Len){
266 return (AttrId << 16) + Len;
267 }
268
269 inline
270 Uint32
BranchCol_2(Uint32 AttrId)271 Interpreter::BranchCol_2(Uint32 AttrId){
272 return (AttrId << 16);
273 }
274
275 inline
276 Uint32
getBinaryCondition(Uint32 op)277 Interpreter::getBinaryCondition(Uint32 op){
278 return (op >> 12) & 0xf;
279 }
280
281 inline
282 Uint32
getArrayLengthDiff(Uint32 op)283 Interpreter::getArrayLengthDiff(Uint32 op){
284 return (op >> 9) & 0x3;
285 }
286
287 inline
288 Uint32
isVarchar(Uint32 op)289 Interpreter::isVarchar(Uint32 op){
290 return (op >> 11) & 1;
291 }
292
293 inline
294 Uint32
getBranchCol_AttrId(Uint32 op)295 Interpreter::getBranchCol_AttrId(Uint32 op){
296 return (op >> 16) & 0xFFFF;
297 }
298
299 inline
300 Uint32
getBranchCol_Len(Uint32 op)301 Interpreter::getBranchCol_Len(Uint32 op){
302 return op & 0xFFFF;
303 }
304
305 inline
306 Uint32
getBranchCol_ParamNo(Uint32 op)307 Interpreter::getBranchCol_ParamNo(Uint32 op){
308 return op & 0xFFFF;
309 }
310
311 inline
312 Uint32
ExitOK()313 Interpreter::ExitOK(){
314 return EXIT_OK;
315 }
316
317 inline
318 Uint32
ExitLastOK()319 Interpreter::ExitLastOK(){
320 return EXIT_OK_LAST;
321 }
322
323 inline
324 Uint32
getOpCode(Uint32 op)325 Interpreter::getOpCode(Uint32 op){
326 return op & 0x3f;
327 }
328
329 inline
330 Uint32
getReg1(Uint32 op)331 Interpreter::getReg1(Uint32 op){
332 return (op >> 6) & 0x7;
333 }
334
335 inline
336 Uint32
getReg2(Uint32 op)337 Interpreter::getReg2(Uint32 op){
338 return (op >> 9) & 0x7;
339 }
340
341 inline
342 Uint32
getReg3(Uint32 op)343 Interpreter::getReg3(Uint32 op){
344 return (op >> 16) & 0x7;
345 }
346
347 inline
348 Uint32
getLabel(Uint32 op)349 Interpreter::getLabel(Uint32 op){
350 return (op >> 16) & 0xffff;
351 }
352
353 inline
354 Uint32*
getInstructionPreProcessingInfo(Uint32 * op,InstructionPreProcessing & processing)355 Interpreter::getInstructionPreProcessingInfo(Uint32 *op,
356 InstructionPreProcessing& processing )
357 {
358 /* Given an instruction, get a pointer to the
359 * next instruction in the stream.
360 * Returns NULL on error.
361 */
362 processing= NONE;
363 Uint32 opCode= getOpCode(*op);
364
365 switch( opCode )
366 {
367 case READ_ATTR_INTO_REG:
368 case WRITE_ATTR_FROM_REG:
369 case LOAD_CONST_NULL:
370 case LOAD_CONST16:
371 return op + 1;
372 case LOAD_CONST32:
373 return op + 2;
374 case LOAD_CONST64:
375 return op + 3;
376 case ADD_REG_REG:
377 case SUB_REG_REG:
378 return op + 1;
379 case BRANCH:
380 case BRANCH_REG_EQ_NULL:
381 case BRANCH_REG_NE_NULL:
382 case BRANCH_EQ_REG_REG:
383 case BRANCH_NE_REG_REG:
384 case BRANCH_LT_REG_REG:
385 case BRANCH_LE_REG_REG:
386 case BRANCH_GT_REG_REG:
387 case BRANCH_GE_REG_REG:
388 processing= LABEL_ADDRESS_REPLACEMENT;
389 return op + 1;
390 case BRANCH_ATTR_OP_ARG:
391 {
392 /* We need to take the length from the second word of the
393 * branch instruction so we can skip over the inline const
394 * comparison data.
395 */
396 processing= LABEL_ADDRESS_REPLACEMENT;
397 Uint32 byteLength= getBranchCol_Len(*(op+1));
398 Uint32 wordLength= (byteLength + 3) >> 2;
399 return op+2+wordLength;
400 }
401 case BRANCH_ATTR_OP_ARG_2:
402 {
403 /* We need to take the length from the second word of the
404 * branch instruction so we can skip over the inline const
405 * comparison data.
406 */
407 processing= LABEL_ADDRESS_REPLACEMENT;
408 return op+2;
409 }
410 case BRANCH_ATTR_EQ_NULL:
411 case BRANCH_ATTR_NE_NULL:
412 processing= LABEL_ADDRESS_REPLACEMENT;
413 return op+2;
414 case EXIT_OK:
415 case EXIT_OK_LAST:
416 case EXIT_REFUSE:
417 return op+1;
418 case CALL:
419 processing= SUB_ADDRESS_REPLACEMENT;
420 case RETURN:
421 return op+1;
422
423 default:
424 return NULL;
425 }
426 }
427
428
429 #undef JAM_FILE_ID
430
431 #endif
432