VapourSynth-llvmexpr
Loading...
Searching...
No Matches
SingleExprIRGenerator.cpp
Go to the documentation of this file.
1
19
21
22#include <format>
23
24#include "llvm/IR/Constants.h"
25#include "llvm/IR/DerivedTypes.h"
26#include "llvm/IR/Function.h"
27#include "llvm/IR/GlobalValue.h"
28#include "llvm/IR/Instructions.h"
29
31 const std::vector<Token>& tokens_in, const VSVideoInfo* out_vi,
32 const std::vector<const VSVideoInfo*>& in_vi, bool mirror,
33 const std::map<std::pair<int, std::string>, int>& p_map,
34 const std::vector<std::string>& output_props,
35 const analysis::ExpressionAnalysisResults& analysis_results_in,
36 llvm::LLVMContext& context_ref, llvm::Module& module_ref,
37 llvm::IRBuilder<>& builder_ref, MathLibraryManager& math_mgr,
38 std::string func_name_in, int approx_math_in)
39 : IRGeneratorBase(tokens_in, out_vi, in_vi, out_vi->width, out_vi->height,
40 mirror, p_map, analysis_results_in, context_ref,
41 module_ref, builder_ref, math_mgr,
42 std::move(func_name_in), approx_math_in),
43 output_props_list(output_props) {
44
45 for (size_t i = 0; i < output_props_list.size(); ++i) {
46 output_prop_map[output_props_list[i]] = static_cast<int>(i);
47 }
48}
49
51 llvm::Type* void_ty = llvm::Type::getVoidTy(context);
52 llvm::Type* ptr_ty = llvm::PointerType::get(context, 0);
53 llvm::Type* context_ptr_ty = ptr_ty; // opaque pointer (void*)
54 llvm::Type* i8_ptr_ptr_ty = ptr_ty; // opaque pointer (represents uint8_t**)
55 llvm::Type* i32_ptr_ty = ptr_ty; // opaque pointer (represents int32_t*)
56 llvm::Type* float_ptr_ty = ptr_ty; // opaque pointer (represents float*)
57
58 llvm::FunctionType* func_ty = llvm::FunctionType::get(
59 void_ty, {context_ptr_ty, i8_ptr_ptr_ty, i32_ptr_ty, float_ptr_ty},
60 false);
61
62 func = llvm::Function::Create(func_ty, llvm::Function::ExternalLinkage,
64 func->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::None);
65
66 context_arg = func->getArg(0);
67 context_arg->setName("context");
68 rwptrs_arg = func->getArg(1);
69 rwptrs_arg->setName("rwptrs");
70 strides_arg = func->getArg(2);
71 strides_arg->setName("strides");
72 props_arg = func->getArg(3);
73 props_arg->setName("props");
74
75 func->addParamAttr(2, llvm::Attribute::ReadOnly); // strides (int32_t*)
76
77 // Declare Host API functions for dynamic array management
78 llvm::Type* i64_ty = builder.getInt64Ty();
79 llvm::Type* i8_ptr_ty = ptr_ty;
80
81 // float* llvmexpr_ensure_buffer(const char* name, int64_t size)
82 llvm::FunctionType* ensure_buffer_ty =
83 llvm::FunctionType::get(float_ptr_ty, {i8_ptr_ty, i64_ty}, false);
84 llvmexpr_ensure_buffer_func = llvm::Function::Create(
85 ensure_buffer_ty, llvm::Function::ExternalLinkage,
86 "llvmexpr_ensure_buffer", &module);
87
88 // int64_t llvmexpr_get_buffer_size(const char* name)
89 llvm::FunctionType* get_buffer_size_ty =
90 llvm::FunctionType::get(i64_ty, {i8_ptr_ty}, false);
91 llvmexpr_get_buffer_size_func = llvm::Function::Create(
92 get_buffer_size_ty, llvm::Function::ExternalLinkage,
93 "llvmexpr_get_buffer_size", &module);
94}
95
97 generateLoops() { // TODO: rename this. Nothing to do with loops here.
98 llvm::BasicBlock* entry_bb =
99 llvm::BasicBlock::Create(context, "entry", func);
100 builder.SetInsertPoint(entry_bb);
101
102 // Pre-load all plane pointers and strides
103 plane_base_ptrs.resize(num_inputs + 1);
104 plane_strides.resize(num_inputs + 1);
105 const int num_planes = // NOLINT(cppcoreguidelines-init-variables)
106 vo->format.numPlanes;
107 for (int i = 0; i <= num_inputs; ++i) {
108 plane_base_ptrs[i].resize(num_planes);
109 plane_strides[i].resize(num_planes);
110 for (int p = 0; p < num_planes; ++p) {
111 int flat_idx = (i * num_planes) + p;
112 llvm::Value* base_ptr_i = builder.CreateLoad(
113 llvm::PointerType::get(context, 0),
114 builder.CreateGEP(llvm::PointerType::get(context, 0),
115 rwptrs_arg, builder.getInt32(flat_idx)));
116 llvm::Value* stride_i = builder.CreateLoad(
117 builder.getInt32Ty(),
118 builder.CreateGEP(builder.getInt32Ty(), strides_arg,
119 builder.getInt32(flat_idx)));
120 plane_base_ptrs[i][p] = base_ptr_i;
121 plane_strides[i][p] = stride_i;
122 }
123 }
124
125 // Aligned loads for properties
126 for (const auto& [key, idx] : prop_map) {
127 llvm::Value* prop_val = builder.CreateLoad(
128 builder.getFloatTy(),
129 builder.CreateGEP(builder.getFloatTy(), props_arg,
130 builder.getInt32(idx)));
131 const std::string unique_prop_name =
132 std::format("prop_{}_{}", key.first, key.second);
133 llvm::Value* alloca =
134 createAllocaInEntry(builder.getFloatTy(), unique_prop_name);
135 builder.CreateStore(prop_val, alloca);
136 prop_allocas[unique_prop_name] = alloca;
137 }
138
139 //NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers)
140 llvm::APInt payload_bits(32, 0x7FC0DEAD);
141 llvm::APFloat nan_payload_apf(llvm::APFloat::IEEEsingle(), payload_bits);
142 llvm::Value* nan_with_payload =
143 llvm::ConstantFP::get(context, nan_payload_apf);
144
145 for (const auto& prop_name : output_props_list) {
146 const std::string mangled_input_name =
147 std::format("prop_0_{}", prop_name);
148 if (prop_allocas.contains(mangled_input_name)) {
149 prop_allocas[prop_name] = prop_allocas.at(mangled_input_name);
150 } else {
151 if (!prop_allocas.contains(prop_name)) {
152 llvm::Value* alloca =
153 createAllocaInEntry(builder.getFloatTy(), prop_name);
154 builder.CreateStore(nan_with_payload, alloca);
155 prop_allocas[prop_name] = alloca;
156 }
157 }
158 }
159
160 // Only generate IR if there are tokens to process
161 if (!tokens.empty()) {
162 generateIRFromTokens(nullptr, nullptr, nullptr, nullptr, true);
163 }
164
165 // Store output properties back
166 for (const auto& [name, idx] : output_prop_map) {
167 llvm::Value* val =
168 builder.CreateLoad(builder.getFloatTy(), prop_allocas.at(name));
169 builder.CreateStore(
170 val,
171 builder.CreateGEP(builder.getFloatTy(), props_arg,
172 builder.getInt32(prop_map.size() + 1 + idx)));
173 }
174
175 builder.CreateRetVoid();
176}
177
178llvm::Value* SingleExprIRGenerator::generatePixelLoadPlane(int clip_idx,
179 int plane_idx,
180 llvm::Value* x,
181 llvm::Value* y) {
182 const VSVideoInfo* vinfo = vi[clip_idx];
183 const VSVideoFormat& format = vinfo->format;
184
185 int plane_w = vinfo->width;
186 int plane_h = vinfo->height;
187 if (format.colorFamily == cfYUV && plane_idx > 0) {
188 plane_w >>= format.subSamplingW;
189 plane_h >>= format.subSamplingH;
190 }
191
192 llvm::Value* final_x =
193 getFinalCoord(x, builder.getInt32(plane_w), mirror_boundary);
194 llvm::Value* final_y =
195 getFinalCoord(y, builder.getInt32(plane_h), mirror_boundary);
196
197 llvm::Value* base_ptr = plane_base_ptrs[clip_idx + 1][plane_idx];
198 llvm::Value* stride = plane_strides[clip_idx + 1][plane_idx];
199
200 llvm::Value* y_offset = builder.CreateMul(final_y, stride);
201 llvm::Value* row_ptr =
202 builder.CreateGEP(builder.getInt8Ty(), base_ptr, y_offset);
203
204 int bpp = format.bytesPerSample;
205
206 llvm::Value* x_offset = builder.CreateMul(final_x, builder.getInt32(bpp));
207 llvm::Value* pixel_addr =
208 builder.CreateGEP(builder.getInt8Ty(), row_ptr, x_offset);
209
210 llvm::Value* loaded_val = nullptr;
211 if (format.sampleType == stInteger) {
212 llvm::Type* load_type = nullptr;
213 if (bpp == 1) {
214 load_type = builder.getInt8Ty();
215 } else if (bpp == 2) {
216 load_type = builder.getInt16Ty();
217 } else {
218 load_type = builder.getInt32Ty();
219 }
220 llvm::LoadInst* li = builder.CreateLoad(load_type, pixel_addr);
221 loaded_val = builder.CreateZExtOrBitCast(li, builder.getInt32Ty());
222 return builder.CreateUIToFP(loaded_val, builder.getFloatTy());
223 } // stFloat
224 if (bpp == 4) {
225 return builder.CreateLoad(builder.getFloatTy(), pixel_addr);
226 }
227 if (bpp == 2) {
228 llvm::Value* half_val =
229 builder.CreateLoad(builder.getHalfTy(), pixel_addr);
230 return builder.CreateFPExt(half_val, builder.getFloatTy());
231 }
232 throw std::runtime_error("Unsupported float sample size.");
233}
234
235void SingleExprIRGenerator::generatePixelStorePlane(llvm::Value* value_to_store,
236 int plane_idx,
237 llvm::Value* x,
238 llvm::Value* y) {
239 const VSVideoFormat& format = vo->format;
240 int bpp = format.bytesPerSample;
241
242 llvm::Value* base_ptr = plane_base_ptrs[0][plane_idx];
243 llvm::Value* stride = plane_strides[0][plane_idx];
244
245 llvm::Value* y_offset = builder.CreateMul(y, stride);
246 llvm::Value* x_offset = builder.CreateMul(x, builder.getInt32(bpp));
247 llvm::Value* total_offset = builder.CreateAdd(y_offset, x_offset);
248 llvm::Value* pixel_addr =
249 builder.CreateGEP(builder.getInt8Ty(), base_ptr, total_offset);
250
251 llvm::Value* final_val = nullptr;
252 if (format.sampleType == stInteger) {
253 int max_val = (1 << format.bitsPerSample) - 1;
254 llvm::Value* zero_f = llvm::ConstantFP::get(builder.getFloatTy(), 0.0);
255 llvm::Value* max_f = llvm::ConstantFP::get(
256 builder.getFloatTy(), static_cast<double>(max_val));
257
258 llvm::Value* temp = createIntrinsicCall(llvm::Intrinsic::maxnum,
259 value_to_store, zero_f);
260 llvm::Value* clamped_f =
261 createIntrinsicCall(llvm::Intrinsic::minnum, temp, max_f);
262
263 llvm::Value* rounded_f =
264 createIntrinsicCall(llvm::Intrinsic::roundeven, clamped_f);
265
266 llvm::Type* store_type = nullptr;
267 if (bpp == 1) {
268 store_type = builder.getInt8Ty();
269 } else if (bpp == 2) {
270 store_type = builder.getInt16Ty();
271 } else {
272 store_type = builder.getInt32Ty();
273 }
274 final_val = builder.CreateFPToUI(rounded_f, store_type);
275 builder.CreateStore(final_val, pixel_addr);
276 } else {
277 if (bpp == 4) {
278 builder.CreateStore(value_to_store, pixel_addr);
279 } else if (bpp == 2) {
280 llvm::Value* truncated_val =
281 builder.CreateFPTrunc(value_to_store, builder.getHalfTy());
282 builder.CreateStore(truncated_val, pixel_addr);
283 } else {
284 throw std::runtime_error("Unsupported float sample size.");
285 }
286 }
287}
288
290 const Token& token, std::vector<llvm::Value*>& rpn_stack,
291 [[maybe_unused]] llvm::Value* x, [[maybe_unused]] llvm::Value* y,
292 [[maybe_unused]] llvm::Value* x_fp, [[maybe_unused]] llvm::Value* y_fp,
293 [[maybe_unused]] bool no_x_bounds_check) {
294 llvm::Type* float_ty = builder.getFloatTy();
295 llvm::Type* i32_ty = builder.getInt32Ty();
296
297 switch (token.type) {
299 const auto& payload = std::get<TokenPayloadClipDim>(token.payload);
300 const VSVideoInfo* vinfo = vi[payload.clip_idx];
301 rpn_stack.push_back(
302 builder.CreateSIToFP(builder.getInt32(vinfo->width), float_ty));
303 return true;
304 }
306 const auto& payload = std::get<TokenPayloadClipDim>(token.payload);
307 const VSVideoInfo* vinfo = vi[payload.clip_idx];
308 rpn_stack.push_back(
309 builder.CreateSIToFP(builder.getInt32(vinfo->height), float_ty));
310 return true;
311 }
313 const auto& payload = std::get<TokenPayloadClipPlaneDim>(token.payload);
314 const VSVideoInfo* vinfo = vi[payload.clip_idx];
315 int plane_w = vinfo->width;
316 if (vinfo->format.colorFamily == cfYUV && payload.plane_idx > 0) {
317 plane_w >>= vinfo->format.subSamplingW;
318 }
319 rpn_stack.push_back(
320 builder.CreateSIToFP(builder.getInt32(plane_w), float_ty));
321 return true;
322 }
324 const auto& payload = std::get<TokenPayloadClipPlaneDim>(token.payload);
325 const VSVideoInfo* vinfo = vi[payload.clip_idx];
326 int plane_h = vinfo->height;
327 if (vinfo->format.colorFamily == cfYUV && payload.plane_idx > 0) {
328 plane_h >>= vinfo->format.subSamplingH;
329 }
330 rpn_stack.push_back(
331 builder.CreateSIToFP(builder.getInt32(plane_h), float_ty));
332 return true;
333 }
335 const auto& payload = std::get<TokenPayloadPlaneDim>(token.payload);
336 int plane_w = vo->width; // NOLINT(cppcoreguidelines-init-variables)
337 if (vo->format.colorFamily == cfYUV && payload.plane_idx > 0) {
338 plane_w >>= vo->format.subSamplingW;
339 }
340 rpn_stack.push_back(
341 builder.CreateSIToFP(builder.getInt32(plane_w), float_ty));
342 return true;
343 }
345 const auto& payload = std::get<TokenPayloadPlaneDim>(token.payload);
346 int plane_h = vo->height; // NOLINT(cppcoreguidelines-init-variables)
347 if (vo->format.colorFamily == cfYUV && payload.plane_idx > 0) {
348 plane_h >>= vo->format.subSamplingH;
349 }
350 rpn_stack.push_back(
351 builder.CreateSIToFP(builder.getInt32(plane_h), float_ty));
352 return true;
353 }
355 const auto& payload =
356 std::get<TokenPayloadClipAccessPlane>(token.payload);
357 llvm::Value* coord_y_f = rpn_stack.back();
358 rpn_stack.pop_back();
359 llvm::Value* coord_x_f = rpn_stack.back();
360 rpn_stack.pop_back();
361
362 llvm::Value* coord_y =
363 builder.CreateCall(llvm::Intrinsic::getOrInsertDeclaration(
364 &module, llvm::Intrinsic::rint, {float_ty}),
365 {coord_y_f});
366 coord_y = builder.CreateFPToSI(coord_y, i32_ty);
367
368 llvm::Value* coord_x =
369 builder.CreateCall(llvm::Intrinsic::getOrInsertDeclaration(
370 &module, llvm::Intrinsic::rint, {float_ty}),
371 {coord_x_f});
372 coord_x = builder.CreateFPToSI(coord_x, i32_ty);
373
374 rpn_stack.push_back(generatePixelLoadPlane(
375 payload.clip_idx, payload.plane_idx, coord_x, coord_y));
376 return true;
377 }
379 const auto& payload =
380 std::get<TokenPayloadStoreAbsPlane>(token.payload);
381 llvm::Value* coord_y_f = rpn_stack.back();
382 rpn_stack.pop_back();
383 llvm::Value* coord_x_f = rpn_stack.back();
384 rpn_stack.pop_back();
385 llvm::Value* val_to_store = rpn_stack.back();
386 rpn_stack.pop_back();
387
388 llvm::Value* coord_y =
389 builder.CreateCall(llvm::Intrinsic::getOrInsertDeclaration(
390 &module, llvm::Intrinsic::rint, {float_ty}),
391 {coord_y_f});
392 coord_y = builder.CreateFPToSI(coord_y, i32_ty);
393
394 llvm::Value* coord_x =
395 builder.CreateCall(llvm::Intrinsic::getOrInsertDeclaration(
396 &module, llvm::Intrinsic::rint, {float_ty}),
397 {coord_x_f});
398 coord_x = builder.CreateFPToSI(coord_x, i32_ty);
399
400 generatePixelStorePlane(val_to_store, payload.plane_idx, coord_x,
401 coord_y);
402 return true;
403 }
405 const auto& payload = std::get<TokenPayloadPropStore>(token.payload);
406 if (payload.type == PropWriteType::Delete) {
407 // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers)
408 llvm::APInt payload_bits(32, 0x7FC0DE1E); // PROP_DELETE_NAN_PAYLOAD
409 llvm::APFloat nan_payload_apf(llvm::APFloat::IEEEsingle(),
410 payload_bits);
411 llvm::Value* nan_with_payload =
412 llvm::ConstantFP::get(context, nan_payload_apf);
413 builder.CreateStore(nan_with_payload,
414 prop_allocas.at(payload.prop_name));
415 } else {
416 llvm::Value* val_to_store = rpn_stack.back();
417 rpn_stack.pop_back();
418 builder.CreateStore(val_to_store,
419 prop_allocas.at(payload.prop_name));
420 }
421 return true;
422 }
424 const auto& payload = std::get<TokenPayloadPropAccess>(token.payload);
425 if (payload.clip_idx == 0 &&
426 output_prop_map.contains(payload.prop_name)) {
427 rpn_stack.push_back(builder.CreateLoad(
428 float_ty, prop_allocas.at(payload.prop_name)));
429 } else {
430 const std::string unique_prop_name =
431 std::format("prop_{}_{}", payload.clip_idx, payload.prop_name);
432 rpn_stack.push_back(builder.CreateLoad(
433 float_ty, prop_allocas.at(unique_prop_name)));
434 }
435 return true;
436 }
437
439 const auto& payload = std::get<TokenPayloadPropAccess>(token.payload);
440 llvm::Value* prop_val = nullptr;
441 if (payload.clip_idx == 0 &&
442 output_prop_map.contains(payload.prop_name)) {
443 prop_val = builder.CreateLoad(float_ty,
444 prop_allocas.at(payload.prop_name));
445 } else {
446 const std::string unique_prop_name =
447 std::format("prop_{}_{}", payload.clip_idx, payload.prop_name);
448 if (!prop_allocas.contains(unique_prop_name)) {
449 rpn_stack.push_back(llvm::ConstantFP::get(float_ty, 0.0));
450 return true;
451 }
452 prop_val =
453 builder.CreateLoad(float_ty, prop_allocas.at(unique_prop_name));
454 }
455
456 llvm::Value* prop_val_int = builder.CreateBitCast(prop_val, i32_ty);
457
458 // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers)
459 llvm::Value* read_nan_payload = builder.getInt32(0x7FC0BEEF);
460 llvm::Value* is_read_nan =
461 builder.CreateICmpEQ(prop_val_int, read_nan_payload);
462
463 // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers)
464 llvm::Value* delete_nan_payload = builder.getInt32(0x7FC0DE1E);
465 llvm::Value* is_delete_nan =
466 builder.CreateICmpEQ(prop_val_int, delete_nan_payload);
467
468 llvm::Value* does_not_exist =
469 builder.CreateOr(is_read_nan, is_delete_nan);
470
471 llvm::Value* exists_val = builder.CreateSelect(
472 does_not_exist, llvm::ConstantFP::get(float_ty, 0.0),
473 llvm::ConstantFP::get(float_ty, 1.0));
474 rpn_stack.push_back(exists_val);
475 return true;
476 }
477
478 // Array
480 const auto& payload = std::get<TokenPayloadArrayOp>(token.payload);
481 llvm::Value* size_val = builder.getInt64(payload.static_size);
482 llvm::Value* name_str =
483 builder.CreateGlobalString(payload.name, payload.name + "_name");
484 llvm::Value* buffer_ptr = builder.CreateCall(
485 llvmexpr_ensure_buffer_func, {name_str, size_val});
486 array_ptr_cache[payload.name] = buffer_ptr;
487 return true;
488 }
489
491 const auto& payload = std::get<TokenPayloadArrayOp>(token.payload);
492 llvm::Value* size_f = rpn_stack.back();
493 rpn_stack.pop_back();
494
495 llvm::Value* size_val =
496 builder.CreateFPToSI(size_f, builder.getInt64Ty());
497 llvm::Value* name_str =
498 builder.CreateGlobalString(payload.name, payload.name + "_name");
499 llvm::Value* buffer_ptr = builder.CreateCall(
500 llvmexpr_ensure_buffer_func, {name_str, size_val});
501 array_ptr_cache[payload.name] = buffer_ptr;
502 return true;
503 }
504
506 const auto& payload = std::get<TokenPayloadArrayOp>(token.payload);
507 llvm::Value* idx_f = rpn_stack.back();
508 rpn_stack.pop_back();
509 llvm::Value* idx = builder.CreateFPToSI(idx_f, i32_ty);
510
511 llvm::Value* array_ptr = array_ptr_cache.at(payload.name);
512 llvm::Value* elem_ptr = builder.CreateGEP(float_ty, array_ptr, idx);
513 llvm::Value* value = builder.CreateLoad(float_ty, elem_ptr);
514 rpn_stack.push_back(value);
515 return true;
516 }
517
519 const auto& payload = std::get<TokenPayloadArrayOp>(token.payload);
520 llvm::Value* idx_f = rpn_stack.back();
521 rpn_stack.pop_back();
522 llvm::Value* value = rpn_stack.back();
523 rpn_stack.pop_back();
524
525 llvm::Value* idx = builder.CreateFPToSI(idx_f, i32_ty);
526
527 llvm::Value* array_ptr = array_ptr_cache.at(payload.name);
528 llvm::Value* elem_ptr = builder.CreateGEP(float_ty, array_ptr, idx);
529 builder.CreateStore(value, elem_ptr);
530 return true;
531 }
532
533 default:
534 return false;
535 }
536}
537
539 [[maybe_unused]] llvm::Value* result_val, [[maybe_unused]] llvm::Value* x,
540 [[maybe_unused]] llvm::Value* y) {
541 // No-op for SingleExpr, all stores are explicit
542}
@ ConstantClipPlaneHeight
Definition Tokenizer.hpp:42
@ ConstantPlaneWidth
Definition Tokenizer.hpp:37
@ ArrayAllocStatic
Definition Tokenizer.hpp:51
@ ConstantPlaneHeight
Definition Tokenizer.hpp:38
@ ConstantClipHeight
Definition Tokenizer.hpp:40
@ ConstantClipPlaneWidth
Definition Tokenizer.hpp:41
@ ConstantClipWidth
Definition Tokenizer.hpp:39
llvm::Value * createIntrinsicCall(llvm::Intrinsic::ID intrinsic_id, Args... args)
const std::map< std::pair< int, std::string >, int > & prop_map
llvm::Value * getFinalCoord(llvm::Value *coord, llvm::Value *max_dim, bool use_mirror)
llvm::IRBuilder & builder
std::string func_name
llvm::LLVMContext & context
const std::vector< const VSVideoInfo * > & vi
void generateIRFromTokens(llvm::Value *x, llvm::Value *y, llvm::Value *x_fp, llvm::Value *y_fp, bool no_x_bounds_check)
llvm::Value * rwptrs_arg
const std::vector< Token > & tokens
IRGeneratorBase(const std::vector< Token > &tokens_in, const VSVideoInfo *out_vi, const std::vector< const VSVideoInfo * > &in_vi, int width_in, int height_in, bool mirror, const std::map< std::pair< int, std::string >, int > &p_map, const analysis::ExpressionAnalysisResults &analysis_results_in, llvm::LLVMContext &context_ref, llvm::Module &module_ref, llvm::IRBuilder<> &builder_ref, MathLibraryManager &math_mgr, std::string func_name_in, int approx_math_in)
llvm::AllocaInst * createAllocaInEntry(llvm::Type *type, const std::string &name)
llvm::Function * func
const VSVideoInfo * vo
llvm::Module & module
llvm::Value * props_arg
llvm::Value * strides_arg
void finalizeAndStoreResult(llvm::Value *result_val, llvm::Value *x, llvm::Value *y) override
bool processModeSpecificToken(const Token &token, std::vector< llvm::Value * > &rpn_stack, llvm::Value *x, llvm::Value *y, llvm::Value *x_fp, llvm::Value *y_fp, bool no_x_bounds_check) override
void defineFunctionSignature() override
SingleExprIRGenerator(const std::vector< Token > &tokens_in, const VSVideoInfo *out_vi, const std::vector< const VSVideoInfo * > &in_vi, bool mirror, const std::map< std::pair< int, std::string >, int > &p_map, const std::vector< std::string > &output_props, const analysis::ExpressionAnalysisResults &analysis_results_in, llvm::LLVMContext &context_ref, llvm::Module &module_ref, llvm::IRBuilder<> &builder_ref, MathLibraryManager &math_mgr, std::string func_name_in, int approx_math_in)
TokenType type
PayloadVariant payload