]>
Commit | Line | Data |
---|---|---|
1d09f67e TL |
1 | // Licensed to the Apache Software Foundation (ASF) under one |
2 | // or more contributor license agreements. See the NOTICE file | |
3 | // distributed with this work for additional information | |
4 | // regarding copyright ownership. The ASF licenses this file | |
5 | // to you under the Apache License, Version 2.0 (the | |
6 | // "License"); you may not use this file except in compliance | |
7 | // with the License. You may obtain a copy of the License at | |
8 | // | |
9 | // http://www.apache.org/licenses/LICENSE-2.0 | |
10 | // | |
11 | // Unless required by applicable law or agreed to in writing, | |
12 | // software distributed under the License is distributed on an | |
13 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
14 | // KIND, either express or implied. See the License for the | |
15 | // specific language governing permissions and limitations | |
16 | // under the License. | |
17 | ||
18 | #pragma once | |
19 | ||
20 | #include <cstdint> | |
21 | #include <memory> | |
22 | #include <string> | |
23 | #include <vector> | |
24 | ||
25 | #include "arrow/util/macros.h" | |
26 | ||
27 | #include "gandiva/annotator.h" | |
28 | #include "gandiva/compiled_expr.h" | |
29 | #include "gandiva/configuration.h" | |
30 | #include "gandiva/dex_visitor.h" | |
31 | #include "gandiva/engine.h" | |
32 | #include "gandiva/execution_context.h" | |
33 | #include "gandiva/function_registry.h" | |
34 | #include "gandiva/gandiva_aliases.h" | |
35 | #include "gandiva/llvm_types.h" | |
36 | #include "gandiva/lvalue.h" | |
37 | #include "gandiva/selection_vector.h" | |
38 | #include "gandiva/value_validity_pair.h" | |
39 | #include "gandiva/visibility.h" | |
40 | ||
41 | namespace gandiva { | |
42 | ||
43 | class FunctionHolder; | |
44 | ||
45 | /// Builds an LLVM module and generates code for the specified set of expressions. | |
46 | class GANDIVA_EXPORT LLVMGenerator { | |
47 | public: | |
48 | /// \brief Factory method to initialize the generator. | |
49 | static Status Make(std::shared_ptr<Configuration> config, | |
50 | std::unique_ptr<LLVMGenerator>* llvm_generator); | |
51 | ||
52 | /// \brief Build the code for the expression trees for default mode. Each | |
53 | /// element in the vector represents an expression tree | |
54 | Status Build(const ExpressionVector& exprs, SelectionVector::Mode mode); | |
55 | ||
56 | /// \brief Build the code for the expression trees for default mode. Each | |
57 | /// element in the vector represents an expression tree | |
58 | Status Build(const ExpressionVector& exprs) { | |
59 | return Build(exprs, SelectionVector::Mode::MODE_NONE); | |
60 | } | |
61 | ||
62 | /// \brief Execute the built expression against the provided arguments for | |
63 | /// default mode. | |
64 | Status Execute(const arrow::RecordBatch& record_batch, | |
65 | const ArrayDataVector& output_vector); | |
66 | ||
67 | /// \brief Execute the built expression against the provided arguments for | |
68 | /// all modes. Only works on the records specified in the selection_vector. | |
69 | Status Execute(const arrow::RecordBatch& record_batch, | |
70 | const SelectionVector* selection_vector, | |
71 | const ArrayDataVector& output_vector); | |
72 | ||
73 | SelectionVector::Mode selection_vector_mode() { return selection_vector_mode_; } | |
74 | LLVMTypes* types() { return engine_->types(); } | |
75 | llvm::Module* module() { return engine_->module(); } | |
76 | std::string DumpIR() { return engine_->DumpIR(); } | |
77 | ||
78 | private: | |
79 | LLVMGenerator(); | |
80 | ||
81 | FRIEND_TEST(TestLLVMGenerator, VerifyPCFunctions); | |
82 | FRIEND_TEST(TestLLVMGenerator, TestAdd); | |
83 | FRIEND_TEST(TestLLVMGenerator, TestNullInternal); | |
84 | ||
85 | llvm::LLVMContext* context() { return engine_->context(); } | |
86 | llvm::IRBuilder<>* ir_builder() { return engine_->ir_builder(); } | |
87 | ||
88 | /// Visitor to generate the code for a decomposed expression. | |
89 | class Visitor : public DexVisitor { | |
90 | public: | |
91 | Visitor(LLVMGenerator* generator, llvm::Function* function, | |
92 | llvm::BasicBlock* entry_block, llvm::Value* arg_addrs, | |
93 | llvm::Value* arg_local_bitmaps, std::vector<llvm::Value*> slice_offsets, | |
94 | llvm::Value* arg_context_ptr, llvm::Value* loop_var); | |
95 | ||
96 | void Visit(const VectorReadValidityDex& dex) override; | |
97 | void Visit(const VectorReadFixedLenValueDex& dex) override; | |
98 | void Visit(const VectorReadVarLenValueDex& dex) override; | |
99 | void Visit(const LocalBitMapValidityDex& dex) override; | |
100 | void Visit(const TrueDex& dex) override; | |
101 | void Visit(const FalseDex& dex) override; | |
102 | void Visit(const LiteralDex& dex) override; | |
103 | void Visit(const NonNullableFuncDex& dex) override; | |
104 | void Visit(const NullableNeverFuncDex& dex) override; | |
105 | void Visit(const NullableInternalFuncDex& dex) override; | |
106 | void Visit(const IfDex& dex) override; | |
107 | void Visit(const BooleanAndDex& dex) override; | |
108 | void Visit(const BooleanOrDex& dex) override; | |
109 | void Visit(const InExprDexBase<int32_t>& dex) override; | |
110 | void Visit(const InExprDexBase<int64_t>& dex) override; | |
111 | void Visit(const InExprDexBase<float>& dex) override; | |
112 | void Visit(const InExprDexBase<double>& dex) override; | |
113 | void Visit(const InExprDexBase<gandiva::DecimalScalar128>& dex) override; | |
114 | void Visit(const InExprDexBase<std::string>& dex) override; | |
115 | template <typename Type> | |
116 | void VisitInExpression(const InExprDexBase<Type>& dex); | |
117 | ||
118 | LValuePtr result() { return result_; } | |
119 | ||
120 | bool has_arena_allocs() { return has_arena_allocs_; } | |
121 | ||
122 | private: | |
123 | enum BufferType { kBufferTypeValidity = 0, kBufferTypeData, kBufferTypeOffsets }; | |
124 | ||
125 | llvm::IRBuilder<>* ir_builder() { return generator_->ir_builder(); } | |
126 | llvm::Module* module() { return generator_->module(); } | |
127 | ||
128 | // Generate the code to build the combined validity (bitwise and) from the | |
129 | // vector of validities. | |
130 | llvm::Value* BuildCombinedValidity(const DexVector& validities); | |
131 | ||
132 | // Generate the code to build the validity and the value for the given pair. | |
133 | LValuePtr BuildValueAndValidity(const ValueValidityPair& pair); | |
134 | ||
135 | // Generate code to build the params. | |
136 | std::vector<llvm::Value*> BuildParams(FunctionHolder* holder, | |
137 | const ValueValidityPairVector& args, | |
138 | bool with_validity, bool with_context); | |
139 | ||
140 | // Generate code to onvoke a function call. | |
141 | LValuePtr BuildFunctionCall(const NativeFunction* func, DataTypePtr arrow_return_type, | |
142 | std::vector<llvm::Value*>* params); | |
143 | ||
144 | // Generate code for an if-else condition. | |
145 | LValuePtr BuildIfElse(llvm::Value* condition, std::function<LValuePtr()> then_func, | |
146 | std::function<LValuePtr()> else_func, | |
147 | DataTypePtr arrow_return_type); | |
148 | ||
149 | // Switch to the entry_block and get reference of the validity/value/offsets buffer | |
150 | llvm::Value* GetBufferReference(int idx, BufferType buffer_type, FieldPtr field); | |
151 | ||
152 | // Get the slice offset of the validity/value/offsets buffer | |
153 | llvm::Value* GetSliceOffset(int idx); | |
154 | ||
155 | // Switch to the entry_block and get reference to the local bitmap. | |
156 | llvm::Value* GetLocalBitMapReference(int idx); | |
157 | ||
158 | // Clear the bit in the local bitmap, if is_valid is 'false' | |
159 | void ClearLocalBitMapIfNotValid(int local_bitmap_idx, llvm::Value* is_valid); | |
160 | ||
161 | LLVMGenerator* generator_; | |
162 | LValuePtr result_; | |
163 | llvm::Function* function_; | |
164 | llvm::BasicBlock* entry_block_; | |
165 | llvm::Value* arg_addrs_; | |
166 | llvm::Value* arg_local_bitmaps_; | |
167 | std::vector<llvm::Value*> slice_offsets_; | |
168 | llvm::Value* arg_context_ptr_; | |
169 | llvm::Value* loop_var_; | |
170 | bool has_arena_allocs_; | |
171 | }; | |
172 | ||
173 | // Generate the code for one expression for default mode, with the output of | |
174 | // the expression going to 'output'. | |
175 | Status Add(const ExpressionPtr expr, const FieldDescriptorPtr output); | |
176 | ||
177 | /// Generate code to load the vector at specified index in the 'arg_addrs' array. | |
178 | llvm::Value* LoadVectorAtIndex(llvm::Value* arg_addrs, int idx, | |
179 | const std::string& name); | |
180 | ||
181 | /// Generate code to load the vector at specified index and cast it as bitmap. | |
182 | llvm::Value* GetValidityReference(llvm::Value* arg_addrs, int idx, FieldPtr field); | |
183 | ||
184 | /// Generate code to load the vector at specified index and cast it as data array. | |
185 | llvm::Value* GetDataReference(llvm::Value* arg_addrs, int idx, FieldPtr field); | |
186 | ||
187 | /// Generate code to load the vector at specified index and cast it as offsets array. | |
188 | llvm::Value* GetOffsetsReference(llvm::Value* arg_addrs, int idx, FieldPtr field); | |
189 | ||
190 | /// Generate code to load the vector at specified index and cast it as buffer pointer. | |
191 | llvm::Value* GetDataBufferPtrReference(llvm::Value* arg_addrs, int idx, FieldPtr field); | |
192 | ||
193 | /// Generate code for the value array of one expression. | |
194 | Status CodeGenExprValue(DexPtr value_expr, int num_buffers, FieldDescriptorPtr output, | |
195 | int suffix_idx, llvm::Function** fn, | |
196 | SelectionVector::Mode selection_vector_mode); | |
197 | ||
198 | /// Generate code to load the local bitmap specified index and cast it as bitmap. | |
199 | llvm::Value* GetLocalBitMapReference(llvm::Value* arg_bitmaps, int idx); | |
200 | ||
201 | /// Generate code to get the bit value at 'position' in the bitmap. | |
202 | llvm::Value* GetPackedBitValue(llvm::Value* bitmap, llvm::Value* position); | |
203 | ||
204 | /// Generate code to get the bit value at 'position' in the validity bitmap. | |
205 | llvm::Value* GetPackedValidityBitValue(llvm::Value* bitmap, llvm::Value* position); | |
206 | ||
207 | /// Generate code to set the bit value at 'position' in the bitmap to 'value'. | |
208 | void SetPackedBitValue(llvm::Value* bitmap, llvm::Value* position, llvm::Value* value); | |
209 | ||
210 | /// Generate code to clear the bit value at 'position' in the bitmap if 'value' | |
211 | /// is false. | |
212 | void ClearPackedBitValueIfFalse(llvm::Value* bitmap, llvm::Value* position, | |
213 | llvm::Value* value); | |
214 | ||
215 | // Generate code to build a DecimalLValue with specified value/precision/scale. | |
216 | std::shared_ptr<DecimalLValue> BuildDecimalLValue(llvm::Value* value, | |
217 | DataTypePtr arrow_type); | |
218 | ||
219 | /// Generate code to make a function call (to a pre-compiled IR function) which takes | |
220 | /// 'args' and has a return type 'ret_type'. | |
221 | llvm::Value* AddFunctionCall(const std::string& full_name, llvm::Type* ret_type, | |
222 | const std::vector<llvm::Value*>& args); | |
223 | ||
224 | /// Compute the result bitmap for the expression. | |
225 | /// | |
226 | /// \param[in] compiled_expr the compiled expression (includes the bitmap indices to be | |
227 | /// used for computing the validity bitmap of the result). | |
228 | /// \param[in] eval_batch (includes input/output buffer addresses) | |
229 | /// \param[in] selection_vector the list of selected positions | |
230 | void ComputeBitMapsForExpr(const CompiledExpr& compiled_expr, | |
231 | const EvalBatch& eval_batch, | |
232 | const SelectionVector* selection_vector); | |
233 | ||
234 | /// Replace the %T in the trace msg with the correct type corresponding to 'type' | |
235 | /// eg. %d for int32, %ld for int64, .. | |
236 | std::string ReplaceFormatInTrace(const std::string& msg, llvm::Value* value, | |
237 | std::string* print_fn); | |
238 | ||
239 | /// Generate the code to print a trace msg with one optional argument (%T) | |
240 | void AddTrace(const std::string& msg, llvm::Value* value = NULLPTR); | |
241 | ||
242 | std::unique_ptr<Engine> engine_; | |
243 | std::vector<std::unique_ptr<CompiledExpr>> compiled_exprs_; | |
244 | FunctionRegistry function_registry_; | |
245 | Annotator annotator_; | |
246 | SelectionVector::Mode selection_vector_mode_; | |
247 | ||
248 | // used for debug | |
249 | bool enable_ir_traces_; | |
250 | std::vector<std::string> trace_strings_; | |
251 | }; | |
252 | ||
253 | } // namespace gandiva |