OpenVDB  11.0.0
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.
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  [] (const std::string&) {} // ignore warnings
124  );
125  const ast::Tree::ConstPtr syntaxTree = ast::parse(code.c_str(), logger);
126  if (!errors.empty()) {
127  std::ostringstream os;
128  for (const auto& e : errors) os << e << "\n";
129  OPENVDB_THROW(AXSyntaxError, os.str());
130  }
131  assert(syntaxTree);
132  typename ExecutableT::Ptr exe = this->compile<ExecutableT>(*syntaxTree, logger, data);
133  if (!errors.empty()) {
134  std::ostringstream os;
135  for (const auto& e : errors) os << e << "\n";
136  OPENVDB_THROW(AXCompilerError, os.str());
137  }
138  assert(exe);
139  return exe;
140  }
141 
142  /// @brief Compile a given AST into an executable object of the given type.
143  /// @param syntaxTree An abstract syntax tree to compile
144  /// @param data Optional external/custom data which is to be referenced by
145  /// the executable object. It allows one to reference data held elsewhere,
146  /// such as inside of a DCC, from inside the AX code
147  /// @note Any errors encountered are collected into a single runtime error
148  template <typename ExecutableT>
149  typename ExecutableT::Ptr
150  compile(const ast::Tree& syntaxTree,
151  const CustomData::Ptr data = CustomData::Ptr())
152  {
153  std::vector<std::string> errors;
154  openvdb::ax::Logger logger(
155  [&errors] (const std::string& error) {
156  errors.emplace_back(error + "\n");
157  },
158  [] (const std::string&) {} // ignore warnings
159  );
160  auto exe = compile<ExecutableT>(syntaxTree, logger, data);
161  if (!errors.empty()) {
162  std::ostringstream os;
163  for (const auto& e : errors) os << e << "\n";
164  OPENVDB_THROW(AXCompilerError, os.str());
165  }
166  assert(exe);
167  return exe;
168  }
169 
170  /// @brief Sets the compiler's function registry object.
171  /// @param functionRegistry A unique pointer to a FunctionRegistry object.
172  /// The compiler will take ownership of the registry that was passed in.
173  /// @todo Perhaps allow one to register individual functions into this
174  /// class rather than the entire registry at once, and/or allow one to
175  /// extract a pointer to the registry and update it manually.
176  void setFunctionRegistry(std::unique_ptr<codegen::FunctionRegistry>&& functionRegistry);
177 
178  ///////////////////////////////////////////////////////////////////////////
179 
180 private:
181  template <typename ExeT, typename GenT>
182  typename ExeT::Ptr
183  compile(const ast::Tree& tree,
184  const std::string& moduleName,
185  const std::vector<std::string>& functions,
186  CustomData::Ptr data,
187  Logger& logger);
188 
189 private:
190  std::shared_ptr<llvm::LLVMContext> mContext;
191  const CompilerOptions mCompilerOptions;
192  std::shared_ptr<codegen::FunctionRegistry> mFunctionRegistry;
193 };
194 
195 
196 } // namespace ax
197 } // namespace OPENVDB_VERSION_NAME
198 } // namespace openvdb
199 
200 #endif // OPENVDB_AX_COMPILER_HAS_BEEN_INCLUDED
201 
Definition: Exceptions.h:39
Definition: Compiler.h:31
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:74
#define OPENVDB_AX_API
Definition: Platform.h:295
Parsing methods for creating abstract syntax trees out of AX code.
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
Single header include which provides methods for initializing AX and running a full AX pipeline (pars...
Logger for collecting errors and warnings that occur during AX compilation.
Definition: Logger.h:57
std::shared_ptr< Compiler > Ptr
Definition: Compiler.h:53
std::unique_ptr< Compiler > UniquePtr
Definition: Compiler.h:54
Settings which control how a Compiler class object behaves.
Definition: CompilerOptions.h:47
Definition: Exceptions.h:13
OpenVDB AX Compiler Options.
void clear()
Clear the tree-code mapping and reset the number of errors/warnings.
std::shared_ptr< const Tree > ConstPtr
Definition: AST.h:564
Logging system to collect errors and warnings throughout the different stages of parsing and compilat...
OPENVDB_AX_API openvdb::ax::ast::Tree::ConstPtr parse(const char *code, ax::Logger &logger)
Construct an abstract syntax tree from a code snippet.
The compiler class. This holds an llvm context and set of compiler options, and constructs executable...
Definition: Compiler.h:49
Access to the CustomData class which can provide custom user user data to the OpenVDB AX Compiler...
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
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
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:121
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:150
Definition: Exceptions.h:37
std::shared_ptr< CustomData > Ptr
Definition: CustomData.h:37
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:212