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