OpenVDB  9.0.1
Compiler.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 compiler/Compiler.h
5 ///
6 /// @authors Nick Avramoussis, Francisco Gochez, Richard Jones
7 ///
8 /// @brief The OpenVDB AX Compiler class provides methods to generate
9 /// AX executables from a provided AX AST (or directly from a given
10 /// string). The class object exists to cache various structures,
11 /// primarily LLVM constructs, which benefit from existing across
12 /// additional compilation runs.
13 ///
14 
15 #ifndef OPENVDB_AX_COMPILER_HAS_BEEN_INCLUDED
16 #define OPENVDB_AX_COMPILER_HAS_BEEN_INCLUDED
17 
18 #include "CompilerOptions.h"
19 #include "CustomData.h"
20 #include "Logger.h"
21 
22 #include "openvdb_ax/ax.h" // backward compat support for initialize()
23 #include "openvdb_ax/ast/Parse.h"
24 
25 #include <openvdb/version.h>
26 
27 #include <memory>
28 #include <sstream>
29 
30 // forward
31 namespace llvm {
32 class LLVMContext;
33 }
34 
35 namespace openvdb {
37 namespace OPENVDB_VERSION_NAME {
38 
39 namespace ax {
40 
41 namespace codegen {
42 // forward
43 class FunctionRegistry;
44 }
45 
46 /// @brief The compiler class. This holds an llvm context and set of compiler
47 /// options, and constructs executable objects (e.g. PointExecutable or
48 /// VolumeExecutable) from a syntax tree or snippet of code.
49 class Compiler
50 {
51 public:
52 
53  using Ptr = std::shared_ptr<Compiler>;
54  using UniquePtr = std::unique_ptr<Compiler>;
55 
56  /// @brief Construct a compiler object with given settings
57  /// @param options CompilerOptions object with various settings
58  Compiler(const CompilerOptions& options = CompilerOptions());
59 
60  ~Compiler() = default;
61 
62  /// @brief Static method for creating Compiler objects
63  static UniquePtr create(const CompilerOptions& options = CompilerOptions());
64 
65  /// @brief Compile a given AST into an executable object of the given type.
66  /// @param syntaxTree An abstract syntax tree to compile
67  /// @param logger Logger for errors and warnings during compilation, this
68  /// should be linked to an ast::Tree and populated with AST node + line
69  /// number mappings for this Tree, e.g. during ast::parse(). This Tree can
70  /// be different from the syntaxTree argument.
71  /// @param data Optional external/custom data which is to be referenced by
72  /// the executable object. It allows one to reference data held elsewhere,
73  /// such as inside of a DCC, from inside the AX code
74  /// @note If the logger has not been populated with AST node and line
75  /// mappings, all messages will appear without valid line and column
76  /// numbers.
77  template <typename ExecutableT>
78  typename ExecutableT::Ptr
79  compile(const ast::Tree& syntaxTree,
80  Logger& logger,
81  const CustomData::Ptr data = CustomData::Ptr());
82 
83  /// @brief Compile a given snippet of AX code into an executable object of
84  /// the given type.
85  /// @param code A string of AX code
86  /// @param logger Logger for errors and warnings during compilation, will be
87  /// cleared of existing data
88  /// @param data Optional external/custom data which is to be referenced by
89  /// the executable object. It allows one to reference data held elsewhere,
90  /// such as inside of a DCC, from inside the AX code
91  /// @note If compilation is unsuccessful, will return nullptr. Logger can
92  /// then be queried for errors.
93  template <typename ExecutableT>
94  typename ExecutableT::Ptr
95  compile(const std::string& code,
96  Logger& logger,
97  const CustomData::Ptr data = CustomData::Ptr())
98  {
99  logger.clear();
100  const ast::Tree::ConstPtr syntaxTree = ast::parse(code.c_str(), logger);
101  if (syntaxTree) return compile<ExecutableT>(*syntaxTree, logger, data);
102  else return nullptr;
103  }
104 
105  /// @brief Compile a given snippet of AX code into an executable object of
106  /// the given type.
107  /// @param code A string of AX code
108  /// @param data Optional external/custom data which is to be referenced by
109  /// the executable object. It allows one to reference data held elsewhere,
110  /// such as inside of a DCC, from inside the AX code
111  /// @note Parser errors are handled separately from compiler errors.
112  /// Each are collected and produce runtime errors.
113  template <typename ExecutableT>
114  typename ExecutableT::Ptr
115  compile(const std::string& code,
116  const CustomData::Ptr data = CustomData::Ptr())
117  {
118  std::vector<std::string> errors;
119  openvdb::ax::Logger logger(
120  [&errors] (const std::string& error) {
121  errors.emplace_back(error + "\n");
122  },
123  // ignore warnings
124  [] (const std::string&) {}
125  );
126  const ast::Tree::ConstPtr syntaxTree = ast::parse(code.c_str(), logger);
127  typename ExecutableT::Ptr exe;
128  if (syntaxTree) {
129  exe = this->compile<ExecutableT>(*syntaxTree, logger, data);
130  }
131  if (!errors.empty()) {
132  std::ostringstream os;
133  for (const auto& e : errors) os << e << "\n";
134  OPENVDB_THROW(AXCompilerError, os.str());
135  }
136  assert(exe);
137  return exe;
138  }
139 
140  /// @brief Compile a given AST into an executable object of the given type.
141  /// @param syntaxTree An abstract syntax tree to compile
142  /// @param data Optional external/custom data which is to be referenced by
143  /// the executable object. It allows one to reference data held elsewhere,
144  /// such as inside of a DCC, from inside the AX code
145  /// @note Any errors encountered are collected into a single runtime error
146  template <typename ExecutableT>
147  typename ExecutableT::Ptr
148  compile(const ast::Tree& syntaxTree,
149  const CustomData::Ptr data = CustomData::Ptr())
150  {
151  std::vector<std::string> errors;
152  openvdb::ax::Logger logger(
153  [&errors] (const std::string& error) {
154  errors.emplace_back(error + "\n");
155  },
156  // ignore warnings
157  [] (const std::string&) {}
158  );
159  auto exe = compile<ExecutableT>(syntaxTree, logger, data);
160  if (!errors.empty()) {
161  std::ostringstream os;
162  for (const auto& e : errors) os << e << "\n";
163  OPENVDB_THROW(AXCompilerError, os.str());
164  }
165  assert(exe);
166  return exe;
167  }
168 
169  /// @brief Sets the compiler's function registry object.
170  /// @param functionRegistry A unique pointer to a FunctionRegistry object.
171  /// The compiler will take ownership of the registry that was passed in.
172  /// @todo Perhaps allow one to register individual functions into this
173  /// class rather than the entire registry at once, and/or allow one to
174  /// extract a pointer to the registry and update it manually.
175  void setFunctionRegistry(std::unique_ptr<codegen::FunctionRegistry>&& functionRegistry);
176 
177  ///////////////////////////////////////////////////////////////////////////
178 
179 private:
180  template <typename ExeT, typename GenT>
181  typename ExeT::Ptr
182  compile(const ast::Tree& tree,
183  const std::string& moduleName,
184  const std::vector<std::string>& functions,
185  CustomData::Ptr data,
186  Logger& logger);
187 
188 private:
189  std::shared_ptr<llvm::LLVMContext> mContext;
190  const CompilerOptions mCompilerOptions;
191  std::shared_ptr<codegen::FunctionRegistry> mFunctionRegistry;
192 };
193 
194 
195 } // namespace ax
196 } // namespace OPENVDB_VERSION_NAME
197 } // namespace openvdb
198 
199 #endif // OPENVDB_AX_COMPILER_HAS_BEEN_INCLUDED
200 
Definition: Compiler.h:31
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:74
The compiler class. This holds an llvm context and set of compiler options, and constructs executable...
Definition: Compiler.h:49
openvdb::ax::ast::Tree::Ptr parse(const char *code)
Construct an abstract syntax tree from a code snippet. A runtime exception will be thrown with the fi...
Parsing methods for creating abstract syntax trees out of AX code.
Definition: Exceptions.h:37
Logger for collecting errors and warnings that occur during AX compilation.
Definition: Logger.h:54
std::unique_ptr< Compiler > UniquePtr
Definition: Compiler.h:54
Single header include which provides methods for initializing AX and running a full AX pipeline (pars...
ExecutableT::Ptr compile(const ast::Tree &syntaxTree, const CustomData::Ptr data=CustomData::Ptr())
Compile a given AST into an executable object of the given type.
Definition: Compiler.h:148
Settings which control how a Compiler class object behaves.
Definition: CompilerOptions.h:47
Definition: Exceptions.h:13
OpenVDB AX Compiler Options.
std::shared_ptr< Compiler > Ptr
Definition: Compiler.h:53
std::shared_ptr< CustomData > Ptr
Definition: CustomData.h:37
ExecutableT::Ptr compile(const std::string &code, const CustomData::Ptr data=CustomData::Ptr())
Compile a given snippet of AX code into an executable object of the given type.
Definition: Compiler.h:115
Logging system to collect errors and warnings throughout the different stages of parsing and compilat...
A Tree is the highest concrete (non-abstract) node in the entire AX AST hierarchy. It represents an entire conversion of a valid AX string.
Definition: AST.h:561
void clear()
Clear the tree-code mapping and reset the number of errors/warnings.
Access to the CustomData class which can provide custom user user data to the OpenVDB AX Compiler...
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:116
std::shared_ptr< const Tree > ConstPtr
Definition: AST.h:564
ExecutableT::Ptr compile(const std::string &code, Logger &logger, const CustomData::Ptr data=CustomData::Ptr())
Compile a given snippet of AX code into an executable object of the given type.
Definition: Compiler.h:95
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:202