OpenVDB 10.0.1
Loading...
Searching...
No Matches
ComputeGenerator.h
Go to the documentation of this file.
1// Copyright Contributors to the OpenVDB Project
2// SPDX-License-Identifier: MPL-2.0
3
4/// @file codegen/ComputeGenerator.h
5///
6/// @authors Nick Avramoussis, Matt Warner, Francisco Gochez, Richard Jones
7///
8/// @brief The core visitor framework for code generation
9///
10
11#ifndef OPENVDB_AX_COMPUTE_GENERATOR_HAS_BEEN_INCLUDED
12#define OPENVDB_AX_COMPUTE_GENERATOR_HAS_BEEN_INCLUDED
13
14#include "FunctionRegistry.h"
15#include "FunctionTypes.h"
16#include "SymbolTable.h"
17
18#include "../ast/AST.h"
19#include "../ast/Visitor.h"
20#include "../compiler/CompilerOptions.h"
21#include "../compiler/Logger.h"
22
23#include <openvdb/version.h>
24
25#include <llvm/Analysis/TargetLibraryInfo.h>
26#include <llvm/IR/BasicBlock.h>
27#include <llvm/IR/Function.h>
28#include <llvm/IR/IRBuilder.h>
29#include <llvm/IR/LLVMContext.h>
30#include <llvm/IR/Module.h>
31
32#include <stack>
33
34namespace openvdb {
36namespace OPENVDB_VERSION_NAME {
37
38namespace ax {
39namespace codegen {
40
41/// @brief The function definition and signature which is built by the
42/// ComputeGenerator.
43///
44/// The argument structure is as follows:
45///
46/// 1) - A void pointer to the CustomData
47///
49{
50 /// The name of the generated function
51 static const std::string Name;
52
53 /// The signature of the generated function
54 using Signature = void(const void* const);
56 static const size_t N_ARGS = FunctionTraitsT::N_ARGS;
57
58 /// The argument key names available during code generation
59 static const std::array<std::string, N_ARGS>& getArgumentKeys();
60 static std::string getDefaultName();
61};
62
63
64///////////////////////////////////////////////////////////////////////////
65///////////////////////////////////////////////////////////////////////////
66
67namespace codegen_internal {
68
69/// @brief Visitor object which will generate llvm IR for a syntax tree. This
70/// provides the majority of the code generation functionality except for
71/// attribute access. This design allows for custom geometry to define their
72/// IR implementations for these accesses by deriving and extending this
73/// generator with ast::Attribute handling (see PointComputeGenerator.h and
74/// VolumeComputeGenerator.h for examples).
75/// @note The visit/traverse methods work slightly differently to the normal
76/// Visitor to allow proper handling of errors and visitation history. Nodes
77/// that inherit from ast::Expression can return false from visit() (and so
78/// traverse()), but this will not necessarily stop traversal altogether.
79/// Instead, any ast::Statements that are not also ast::Expressions i.e.
80/// Block, ConditionalStatement, Loop, DeclareLocal, etc override their visit
81/// and traverse methods to handle custom traversal order, and the catching
82/// of failed child Expression visit/traverse calls. This allows errors in
83/// independent Statements to not halt traversal for future Statements and so
84/// allow capturing of multiple errors in an ast::Tree in a single call to
85/// ComputeGenerator::generate().
86struct OPENVDB_AX_API ComputeGenerator : public ast::Visitor<ComputeGenerator>
87{
88 ComputeGenerator(llvm::Module& module,
89 const FunctionOptions& options,
90 FunctionRegistry& functionRegistry,
91 Logger& logger);
92
93 virtual ~ComputeGenerator() = default;
94
95 bool generate(const ast::Tree&);
96
97 inline SymbolTable& globals() { return mSymbolTables.globals(); }
98 inline const SymbolTable& globals() const { return mSymbolTables.globals(); }
99
100 // Visitor pattern
101
102 using ast::Visitor<ComputeGenerator>::traverse;
103 using ast::Visitor<ComputeGenerator>::visit;
104
105 /// @brief Code generation always runs post order
106 inline bool postOrderNodes() const { return true; }
107
108 /// @brief Custom traversal of scoped blocks
109 /// @note This overrides the default traversal to incorporate
110 /// the scoping of variables declared in this block
111 bool traverse(const ast::Block* block)
112 {
113 if (!block) return true;
114 if (!this->visit(block)) return false;
115 return true;
116 }
117
118 /// @brief Custom traversal of comma expression
119 /// @note This overrides the default traversal to handle errors
120 /// without stopping generation of entire list
121 /// @todo Replace with a binary operator that simply returns the second value
122 bool traverse(const ast::CommaOperator* comma)
123 {
124 if (!comma) return true;
125 if (!this->visit(comma)) return false;
126 return true;
127 }
128
129
130 /// @brief Custom traversal of conditional statements
131 /// @note This overrides the default traversal to handle
132 /// branching between different code paths
134 {
135 if (!cond) return true;
136 if (!this->visit(cond)) return false;
137 return true;
138 }
139
140 /// @brief Custom traversal of binary operators
141 /// @note This overrides the default traversal to handle
142 /// short-circuiting in logical AND and OR
144 {
145 if (!bin) return true;
146 if (!this->visit(bin)) return false;
147 return true;
148 }
149
150 /// @brief Custom traversal of ternary operators
151 /// @note This overrides the default traversal to handle
152 /// branching between different code paths
154 {
155 if (!tern) return true;
156 if (!this->visit(tern)) return false;
157 return true;
158 }
159
160 /// @brief Custom traversal of loops
161 /// @note This overrides the default traversal to handle
162 /// branching between different code paths and the
163 /// scoping of variables in for-loop initialisation
164 bool traverse(const ast::Loop* loop)
165 {
166 if (!loop) return true;
167 if (!this->visit(loop)) return false;
168 return true;
169 }
170
171 /// @brief Custom traversal of declarations
172 /// @note This overrides the default traversal to
173 /// handle traversal of the local and
174 /// assignment of initialiser, if it exists
175 bool traverse(const ast::DeclareLocal* decl)
176 {
177 if (!decl) return true;
178 if (!this->visit(decl)) return false;
179 return true;
180 }
181
182 ///@{
183 /// @brief Visitor methods for all AST nodes which implement IR generation
184 virtual bool visit(const ast::CommaOperator*);
185 virtual bool visit(const ast::AssignExpression*);
186 virtual bool visit(const ast::Crement*);
187 virtual bool visit(const ast::FunctionCall*);
188 virtual bool visit(const ast::Attribute*);
189 virtual bool visit(const ast::Tree*);
190 virtual bool visit(const ast::Block*);
191 virtual bool visit(const ast::ConditionalStatement*);
192 virtual bool visit(const ast::Loop*);
193 virtual bool visit(const ast::Keyword*);
194 virtual bool visit(const ast::UnaryOperator*);
195 virtual bool visit(const ast::BinaryOperator*);
196 virtual bool visit(const ast::TernaryOperator*);
197 virtual bool visit(const ast::Cast*);
198 virtual bool visit(const ast::DeclareLocal*);
199 virtual bool visit(const ast::Local*);
200 virtual bool visit(const ast::ExternalVariable*);
201 virtual bool visit(const ast::ArrayUnpack*);
202 virtual bool visit(const ast::ArrayPack*);
203 virtual bool visit(const ast::Value<bool>*);
204 virtual bool visit(const ast::Value<int16_t>*);
205 virtual bool visit(const ast::Value<int32_t>*);
206 virtual bool visit(const ast::Value<int64_t>*);
207 virtual bool visit(const ast::Value<float>*);
208 virtual bool visit(const ast::Value<double>*);
209 virtual bool visit(const ast::Value<std::string>*);
210
211 template <typename ValueType>
212 typename std::enable_if<std::is_integral<ValueType>::value, bool>::type
214 template <typename ValueType>
215
216 typename std::enable_if<std::is_floating_point<ValueType>::value, bool>::type
218 ///@}
219
220protected:
221 const FunctionGroup* getFunction(const std::string& identifier,
222 const bool allowInternal = false);
223
224 bool binaryExpression(llvm::Value*& result, llvm::Value* lhs, llvm::Value* rhs,
225 const ast::tokens::OperatorToken op, const ast::Node* node);
226 bool assignExpression(llvm::Value* lhs, llvm::Value*& rhs, const ast::Node* node);
227
228 /// @brief Clear any strings which were allocated in a given function.
229 /// This method accepts an IRBuilder which is expected to be attached to
230 /// a valid block/function. For each block in the function with a return
231 /// instruction, this function calls the appropriate memory methods to
232 /// deallocate any strings (which are alloced in the function prologue).
233 void createFreeSymbolStrings(llvm::IRBuilder<>&);
234
235 llvm::Module& mModule;
236 llvm::LLVMContext& mContext;
237 llvm::IRBuilder<> mBuilder;
238
239 // The stack of accessed values
240 std::stack<llvm::Value*> mValues;
241
242 // The stack of blocks for keyword branching
243 std::stack<std::pair<llvm::BasicBlock*, llvm::BasicBlock*>> mBreakContinueStack;
244
245 // The current scope number used to track scoped declarations
247
248 // The map of scope number to local variable names to values
250
251 // The function used as the base code block
252 llvm::Function* mFunction;
253
255
257
258private:
259 FunctionRegistry& mFunctionRegistry;
260};
261
262} // codegen_internal
263
264} // namespace codegen
265} // namespace ax
266} // namespace OPENVDB_VERSION_NAME
267} // namespace openvdb
268
269#endif // OPENVDB_AX_COMPUTE_GENERATOR_HAS_BEEN_INCLUDED
270
Contains the global function registration definition which described all available user front end fun...
Contains frameworks for creating custom AX functions which can be registered within the FunctionRegis...
#define OPENVDB_AX_API
Definition: Platform.h:272
Contains the symbol table which holds mappings of variables names to llvm::Values.
Logger for collecting errors and warnings that occur during AX compilation.
Definition: Logger.h:58
The function registry which is used for function code generation. Each time a function is visited wit...
Definition: FunctionRegistry.h:36
OperatorToken
Definition: Tokens.h:151
Definition: Exceptions.h:13
Options that control how functions behave.
Definition: CompilerOptions.h:25
ArrayPacks represent temporary container creations of arbitrary sizes, typically generated through th...
Definition: AST.h:1785
ArrayUnpack represent indexing operations into AX container types, primarily vectors and matrices ind...
Definition: AST.h:1686
AssignExpressions represents a similar object construction to a BinaryOperator. AssignExpressions can...
Definition: AST.h:1198
Attributes represent any access to a primitive value, typically associated with the '@' symbol syntax...
Definition: AST.h:1874
A BinaryOperator represents a single binary operation between a left hand side (LHS) and right hand s...
Definition: AST.h:988
A Block node represents a scoped list of statements. It may comprise of 0 or more statements,...
Definition: AST.h:476
Cast nodes represent the conversion of an underlying expression to a target type. Cast nodes are typi...
Definition: AST.h:1464
ConditionalStatements represents all combinations of 'if', 'else' and 'else if' syntax and semantics....
Definition: AST.h:864
A Crement node represents a single increment '++' and decrement '–' operation. As well as it's cremen...
Definition: AST.h:1294
DeclareLocal AST nodes symbolize a single type declaration of a local variable. These store the local...
Definition: AST.h:2139
ExternalVariable represent any access to external (custom) data, typically associated with the '$' sy...
Definition: AST.h:2002
FunctionCalls represent a single call to a function and any provided arguments. The argument list can...
Definition: AST.h:1541
Keywords represent keyword statements defining changes in execution. These include those that define ...
Definition: AST.h:1641
Local AST nodes represent a single accesses to a local variable. The only store the name of the varia...
Definition: AST.h:2112
Loops represent for, while and do-while loop constructs. These all consist of a condition - evaluated...
Definition: AST.h:708
The base abstract node which determines the interface and required methods for all derived concrete n...
Definition: AST.h:102
A TernaryOperator represents a ternary (conditional) expression 'a ? b : c' which evaluates to 'b' if...
Definition: AST.h:1092
A Tree is the highest concrete (non-abstract) node in the entire AX AST hierarchy....
Definition: AST.h:562
A UnaryOperator represents a single unary operation on an expression. The operation type is stored as...
Definition: AST.h:1389
A Value (literal) AST node holds either literal text or absolute value information on all numerical,...
Definition: AST.h:2253
The Visitor class uses the Curiously Recursive Template Pattern (CRTP) to provide a customizable inte...
Definition: Visitor.h:96
The function definition and signature which is built by the ComputeGenerator.
Definition: ComputeGenerator.h:49
void(const void *const) Signature
The signature of the generated function.
Definition: ComputeGenerator.h:54
static const std::string Name
The name of the generated function.
Definition: ComputeGenerator.h:51
static const std::array< std::string, N_ARGS > & getArgumentKeys()
The argument key names available during code generation.
todo
Definition: FunctionTypes.h:793
Templated function traits which provides compile-time index access to the types of the function signa...
Definition: Types.h:279
A map of unique ids to symbol tables which can be used to represent local variables within a program....
Definition: SymbolTable.h:113
A symbol table which can be used to represent a single scoped set of a programs variables....
Definition: SymbolTable.h:36
Visitor object which will generate llvm IR for a syntax tree. This provides the majority of the code ...
Definition: ComputeGenerator.h:87
virtual bool visit(const ast::ExternalVariable *)
Visitor methods for all AST nodes which implement IR generation.
SymbolTableBlocks mSymbolTables
Definition: ComputeGenerator.h:249
virtual bool visit(const ast::Value< std::string > *)
Visitor methods for all AST nodes which implement IR generation.
std::stack< std::pair< llvm::BasicBlock *, llvm::BasicBlock * > > mBreakContinueStack
Definition: ComputeGenerator.h:243
SymbolTable & globals()
Definition: ComputeGenerator.h:97
ComputeGenerator(llvm::Module &module, const FunctionOptions &options, FunctionRegistry &functionRegistry, Logger &logger)
virtual bool visit(const ast::Tree *)
Visitor methods for all AST nodes which implement IR generation.
virtual bool visit(const ast::Keyword *)
Visitor methods for all AST nodes which implement IR generation.
bool traverse(const ast::BinaryOperator *bin)
Custom traversal of binary operators.
Definition: ComputeGenerator.h:143
void createFreeSymbolStrings(llvm::IRBuilder<> &)
Clear any strings which were allocated in a given function. This method accepts an IRBuilder which is...
virtual bool visit(const ast::Crement *)
Visitor methods for all AST nodes which implement IR generation.
virtual bool visit(const ast::Cast *)
Visitor methods for all AST nodes which implement IR generation.
virtual bool visit(const ast::BinaryOperator *)
Visitor methods for all AST nodes which implement IR generation.
llvm::Module & mModule
Definition: ComputeGenerator.h:235
virtual bool visit(const ast::Local *)
Visitor methods for all AST nodes which implement IR generation.
bool traverse(const ast::Loop *loop)
Custom traversal of loops.
Definition: ComputeGenerator.h:164
const FunctionOptions mOptions
Definition: ComputeGenerator.h:254
virtual bool visit(const ast::TernaryOperator *)
Visitor methods for all AST nodes which implement IR generation.
virtual bool visit(const ast::Value< int16_t > *)
Visitor methods for all AST nodes which implement IR generation.
bool traverse(const ast::CommaOperator *comma)
Custom traversal of comma expression.
Definition: ComputeGenerator.h:122
llvm::Function * mFunction
Definition: ComputeGenerator.h:252
virtual bool visit(const ast::AssignExpression *)
Visitor methods for all AST nodes which implement IR generation.
bool traverse(const ast::ConditionalStatement *cond)
Custom traversal of conditional statements.
Definition: ComputeGenerator.h:133
virtual bool visit(const ast::Loop *)
Visitor methods for all AST nodes which implement IR generation.
virtual bool visit(const ast::Attribute *)
Visitor methods for all AST nodes which implement IR generation.
llvm::IRBuilder mBuilder
Definition: ComputeGenerator.h:237
bool postOrderNodes() const
Code generation always runs post order.
Definition: ComputeGenerator.h:106
virtual bool visit(const ast::ConditionalStatement *)
Visitor methods for all AST nodes which implement IR generation.
bool traverse(const ast::DeclareLocal *decl)
Custom traversal of declarations.
Definition: ComputeGenerator.h:175
virtual bool visit(const ast::Value< bool > *)
Visitor methods for all AST nodes which implement IR generation.
const FunctionGroup * getFunction(const std::string &identifier, const bool allowInternal=false)
llvm::LLVMContext & mContext
Definition: ComputeGenerator.h:236
virtual bool visit(const ast::Block *)
Visitor methods for all AST nodes which implement IR generation.
bool traverse(const ast::TernaryOperator *tern)
Custom traversal of ternary operators.
Definition: ComputeGenerator.h:153
virtual bool visit(const ast::FunctionCall *)
Visitor methods for all AST nodes which implement IR generation.
virtual bool visit(const ast::DeclareLocal *)
Visitor methods for all AST nodes which implement IR generation.
virtual bool visit(const ast::UnaryOperator *)
Visitor methods for all AST nodes which implement IR generation.
bool binaryExpression(llvm::Value *&result, llvm::Value *lhs, llvm::Value *rhs, const ast::tokens::OperatorToken op, const ast::Node *node)
virtual bool visit(const ast::ArrayPack *)
Visitor methods for all AST nodes which implement IR generation.
const SymbolTable & globals() const
Definition: ComputeGenerator.h:98
Logger & mLog
Definition: ComputeGenerator.h:256
virtual bool visit(const ast::Value< int32_t > *)
Visitor methods for all AST nodes which implement IR generation.
bool traverse(const ast::Block *block)
Custom traversal of scoped blocks.
Definition: ComputeGenerator.h:111
std::stack< llvm::Value * > mValues
Definition: ComputeGenerator.h:240
std::enable_if< std::is_integral< ValueType >::value, bool >::type visit(const ast::Value< ValueType > *node)
Visitor methods for all AST nodes which implement IR generation.
std::enable_if< std::is_floating_point< ValueType >::value, bool >::type visit(const ast::Value< ValueType > *node)
Visitor methods for all AST nodes which implement IR generation.
size_t mScopeIndex
Definition: ComputeGenerator.h:246
virtual bool visit(const ast::Value< int64_t > *)
Visitor methods for all AST nodes which implement IR generation.
virtual bool visit(const ast::ArrayUnpack *)
Visitor methods for all AST nodes which implement IR generation.
bool assignExpression(llvm::Value *lhs, llvm::Value *&rhs, const ast::Node *node)
virtual bool visit(const ast::Value< float > *)
Visitor methods for all AST nodes which implement IR generation.
virtual bool visit(const ast::CommaOperator *)
Visitor methods for all AST nodes which implement IR generation.
virtual bool visit(const ast::Value< double > *)
Visitor methods for all AST nodes which implement IR generation.
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:121
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:212