github.com/rohankumardubey/aresdb@v0.0.2-0.20190517170215-e54e3ca06b9c/query/expression_vm.h (about) 1 // Copyright (c) 2017-2018 Uber Technologies, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #ifndef QUERY_EXPRESSION_VM_H_ 16 #define QUERY_EXPRESSION_VM_H_ 17 #include <stddef.h> 18 #include <stdint.h> 19 20 // The expression VM is a stack based interpreter that evaluates expressions 21 // (filter, dimension, pre-aggregate measure) on GPUs. 22 // For simplicity each instruction is a 32-bit word using the following format: 23 // Bits masked by 0xff000000 defines the instruction itself. 24 // Bits masked by 0x0000ffff defines the payload of the instruction. 25 // 26 // A pair of value/null stack is used to process SQL expressions. 27 // Each slot in the value stack always takes 4 bytes, regardless of the type, 28 // while each slot in the null stack takes 1 byte. 29 // Both stack grows up from lower address to higher address. 30 enum ExprVMInst { 31 // End of the instruction sequence, stops the expression VM. 32 INST_EOF = 0, 33 34 // Invokes a function call with the top X parameters on the stack pair. 35 // The last parameter is on top of the stack, while the first is the deepest 36 // in the stack. 37 // The call type is specified in the payload (masked by 0x0000ffff). 38 // At the end of the call, the result is put on top of the stack pair. 39 // 40 // TODO(lucafuji): to support an argument with variable-length data 41 // (e.g., geofence), 42 // We need to add a third stack for storing offsets to the value stack, 43 // and introduce new instructions that operate on the offset stack. 44 INST_CALL = 0x01000000, 45 46 // Reads from an input column and pushes it onto the top of the stack pair. 47 // The payload (masked by 0x0000ffff) defines index to the column to be read 48 // from the global (query-wise) column array. Values are always stored using 49 // 4 bytes regardless of their types for simplicity. 50 INST_PUSH = 0x02000000, 51 52 // The following instructions push a constant onto the top of the stack pair. 53 // To push a small integer that fits in a 16-bit word, simply put the integer 54 // as the payload of INST_PUSH_CONST_LOW. 55 // To push a big integer that does not fit, first split it to lower 16 bits 56 // and higher 16 bits, then put the lower 16 bits as the payload of 57 // INST_PUSH_CONST_LOW, then put the higher 16 bits as the payload of 58 // INST_WRITE_CONST_HIGH. Note that INST_WRITE_CONST_HIGH writes the payload 59 // to the higher 16 bits of the word on top of the value stack, without moving 60 // the stack pointer. 61 INST_PUSH_CONST_NULL = 0x03000000, 62 INST_PUSH_CONST_LOW = 0x04000000, 63 INST_WRITE_CONST_HIGH = 0x05000000, 64 65 // Skips the next X instructions when the top of the value stack is 66 // zero/non-zero. X is specified in the payload (masked by 0x0000ffff). 67 // The purpose of this instruction is to allow short-circuiting in logical 68 // expresions, and to allow case-when-then-else-end (if-else) expression. 69 INST_JZ = 0x06000000, 70 INST_JNZ = 0x07000000, 71 72 // Skips the next X instructions. 73 // X is specified in the payload (masked by 0x0000ffff). 74 // The purpose of this instruction is to allow case-when-then-else-end 75 // (if-else) expression (jumping from the end of if block to end of else). 76 INST_JMP = 0x08000000 77 }; 78 79 // ExprVMCall defines the call types of all operators and (non-aggregate) 80 // functions. UDF functions also share the same call type space. 81 enum ExprVMCall { 82 // Unary OPs 83 CALL_NEG = 0x01, 84 CALL_NEG_FLOAT = 0x02, 85 CALL_NOT = 0x03, 86 CALL_BITWISE_NOT = 0x04, 87 CALL_SIGNED_TO_FLOAT = 0x05, 88 CALL_UNSIGNED_TO_FLOAT = 0x06, 89 CALL_FLOAT_TO_SIGNED = 0x07, 90 CALL_FLOAT_TO_UNSIGNED = 0x08, 91 92 // Operators above this line do not need to modify the null stack. 93 call_begin_null_ops = 0x0d, 94 95 CALL_IS_NULL = 0x0e, 96 CALL_IS_NOT_NULL = 0x0f, 97 98 // Binary OPs 99 call_begin_binary_ops = 0x10, 100 101 CALL_IS = 0x11, 102 // In SQL expression: NULL AND FALSE = FALSE, NULL OR TRUE = TRUE... 103 CALL_AND = 0x12, 104 CALL_OR = 0x13, 105 106 call_end_null_ops = 0x14, 107 // Operators below this line can simply run nulls[0] = nulls[0] && nulls[1] to 108 // handle nulls. Note that the null stack stores validity. 109 110 CALL_XOR = 0x21, 111 CALL_BITWISE_AND = 0x22, 112 CALL_BITWISE_OR = 0x23, 113 CALL_BITWISE_XOR = 0x24, 114 CALL_SHL = 0x25, 115 CALL_SHR = 0x26, 116 CALL_EQ = 0x27, 117 CALL_EQ_FLOAT = 0x28, 118 CALL_LT_SIGNED = 0x29, 119 CALL_LT_UNSIGNED = 0x2a, 120 CALL_LT_FLOAT = 0x2b, 121 CALL_LE_SIGNED = 0x2c, 122 CALL_LE_UNSIGNED = 0x2d, 123 CALL_LE_FLOAT = 0x2e, 124 125 CALL_ADD = 0x31, 126 CALL_ADD_FLOAT = 0x32, 127 CALL_SUB = 0x33, 128 CALL_SUB_FLOAT = 0x34, 129 CALL_MUL_SIGNED = 0x35, 130 CALL_MUL_UNSIGNED = 0x36, 131 CALL_MUL_FLOAT = 0x37, 132 CALL_DIV_SIGNED = 0x38, 133 CALL_DIV_UNSIGNED = 0x39, 134 CALL_DIV_FLOAT = 0x3a, 135 CALL_MOD_SIGNED = 0x3b, 136 CALL_MOD_UNSIGNED = 0x3c, 137 CALL_MOD_FLOAT = 0x3d 138 }; 139 #endif // QUERY_EXPRESSION_VM_H_