OpenVDB  10.0.0
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 
34 namespace openvdb {
36 namespace OPENVDB_VERSION_NAME {
37 
38 namespace ax {
39 namespace 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 
67 namespace 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().
86 struct 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 
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
143  bool traverse(const ast::BinaryOperator* bin)
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
153  bool traverse(const ast::TernaryOperator* tern)
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>
214  template <typename ValueType>
215 
218  ///@}
219 
220 protected:
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
246  size_t mScopeIndex;
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 
258 private:
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...
ValueT value
Definition: GridBuilder.h:1290
#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
Specialization of Values for strings.
Definition: AST.h:2335
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::array< std::string, N_ARGS > & getArgumentKeys()
The argument key names available during code generation.
static const std::string Name
The name of the generated function.
Definition: ComputeGenerator.h:51
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
ComputeGenerator(llvm::Module &module, const FunctionOptions &options, FunctionRegistry &functionRegistry, Logger &logger)
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.
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.
SymbolTable & globals()
Definition: ComputeGenerator.h:97
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
const SymbolTable & globals() const
Definition: ComputeGenerator.h:98
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
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.
virtual bool visit(const ast::Value< bool > *)
Visitor methods for all AST nodes which implement IR generation.
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.
const FunctionGroup * getFunction(const std::string &identifier, const bool allowInternal=false)
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.
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
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