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