OpenVDB  10.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.
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 
std::shared_ptr< CustomData > Ptr
Definition: CustomData.h:37
Definition: Compiler.h:31
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:74
std::unique_ptr< Compiler > UniquePtr
Definition: Compiler.h:54
Settings which control how a Compiler class object behaves.
Definition: CompilerOptions.h:47
#define OPENVDB_AX_API
Definition: Platform.h:272
Parsing methods for creating abstract syntax trees out of AX code.
void clear()
Clear the tree-code mapping and reset the number of errors/warnings.
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:150
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
Definition: Exceptions.h:13
Logger for collecting errors and warnings that occur during AX compilation.
Definition: Logger.h:57
OpenVDB AX Compiler Options.
OPENVDB_AX_API openvdb::ax::ast::Tree::ConstPtr parse(const char *code, ax::Logger &logger)
Construct an abstract syntax tree from a code snippet.
Logging system to collect errors and warnings throughout the different stages of parsing and compilat...
The compiler class. This holds an llvm context and set of compiler options, and constructs executable...
Definition: Compiler.h:49
Definition: Exceptions.h:39
Access to the CustomData class which can provide custom user user data to the OpenVDB AX Compiler...
std::shared_ptr< const Tree > ConstPtr
Definition: AST.h:564
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:121
std::shared_ptr< Compiler > Ptr
Definition: Compiler.h:53
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
Definition: Exceptions.h:37
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:212